@eagleoutice/flowr 2.2.13 → 2.2.15

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 (145) hide show
  1. package/README.md +4 -4
  2. package/cli/repl/commands/repl-cfg.d.ts +2 -2
  3. package/cli/repl/commands/repl-cfg.js +4 -4
  4. package/cli/repl/commands/repl-commands.js +3 -3
  5. package/cli/repl/commands/repl-execute.js +2 -1
  6. package/cli/repl/server/connection.js +1 -1
  7. package/cli/script-core/statistics-helper-core.js +1 -1
  8. package/config.js +1 -1
  9. package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
  10. package/control-flow/cfg-dead-code.d.ts +4 -0
  11. package/control-flow/cfg-dead-code.js +81 -0
  12. package/control-flow/cfg-simplification.d.ts +17 -6
  13. package/control-flow/cfg-simplification.js +23 -19
  14. package/control-flow/control-flow-graph.d.ts +2 -1
  15. package/control-flow/control-flow-graph.js +1 -0
  16. package/control-flow/dfg-cfg-guided-visitor.d.ts +4 -4
  17. package/control-flow/dfg-cfg-guided-visitor.js +1 -1
  18. package/control-flow/extract-cfg.d.ts +2 -2
  19. package/control-flow/extract-cfg.js +70 -67
  20. package/control-flow/semantic-cfg-guided-visitor.d.ts +17 -8
  21. package/control-flow/semantic-cfg-guided-visitor.js +50 -17
  22. package/control-flow/simple-visitor.d.ts +4 -0
  23. package/control-flow/simple-visitor.js +14 -0
  24. package/control-flow/syntax-cfg-guided-visitor.d.ts +2 -2
  25. package/dataflow/environments/built-in-config.d.ts +1 -0
  26. package/dataflow/environments/built-in.d.ts +10 -1
  27. package/dataflow/environments/built-in.js +9 -3
  28. package/dataflow/environments/default-builtin-config.js +1 -1
  29. package/dataflow/environments/resolve-by-name.d.ts +0 -36
  30. package/dataflow/environments/resolve-by-name.js +0 -240
  31. package/dataflow/eval/resolve/alias-tracking.d.ts +87 -0
  32. package/dataflow/eval/resolve/alias-tracking.js +349 -0
  33. package/dataflow/eval/resolve/resolve.d.ts +34 -0
  34. package/dataflow/eval/resolve/resolve.js +93 -0
  35. package/dataflow/eval/values/general.d.ts +27 -0
  36. package/dataflow/eval/values/general.js +73 -0
  37. package/dataflow/eval/values/intervals/interval-constants.d.ts +4 -0
  38. package/dataflow/eval/values/intervals/interval-constants.js +27 -0
  39. package/dataflow/eval/values/logical/logical-constants.d.ts +7 -0
  40. package/dataflow/eval/values/logical/logical-constants.js +31 -0
  41. package/dataflow/eval/values/r-value.d.ts +58 -0
  42. package/dataflow/eval/values/r-value.js +90 -0
  43. package/dataflow/eval/values/scalar/scalar-consatnts.d.ts +15 -0
  44. package/dataflow/eval/values/scalar/scalar-consatnts.js +35 -0
  45. package/dataflow/eval/values/sets/set-constants.d.ts +7 -0
  46. package/dataflow/eval/values/sets/set-constants.js +34 -0
  47. package/dataflow/eval/values/string/string-constants.d.ts +8 -0
  48. package/dataflow/eval/values/string/string-constants.js +40 -0
  49. package/dataflow/eval/values/vectors/vector-constants.d.ts +14 -0
  50. package/dataflow/eval/values/vectors/vector-constants.js +35 -0
  51. package/dataflow/graph/unknown-replacement.d.ts +11 -0
  52. package/dataflow/graph/unknown-replacement.js +12 -0
  53. package/dataflow/graph/unknown-side-effect.d.ts +7 -0
  54. package/dataflow/graph/unknown-side-effect.js +13 -0
  55. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +8 -5
  56. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +4 -2
  57. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +12 -9
  58. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -4
  59. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +9 -2
  60. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +12 -15
  61. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +23 -0
  62. package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
  63. package/documentation/doc-util/doc-cfg.d.ts +1 -1
  64. package/documentation/doc-util/doc-cfg.js +3 -3
  65. package/documentation/doc-util/doc-query.d.ts +6 -3
  66. package/documentation/doc-util/doc-query.js +3 -1
  67. package/documentation/print-cfg-wiki.js +31 -31
  68. package/documentation/print-dataflow-graph-wiki.js +4 -3
  69. package/documentation/print-engines-wiki.js +1 -1
  70. package/documentation/print-linter-wiki.d.ts +1 -0
  71. package/documentation/print-linter-wiki.js +76 -0
  72. package/documentation/print-query-wiki.js +80 -0
  73. package/linter/linter-executor.d.ts +9 -0
  74. package/linter/linter-executor.js +26 -0
  75. package/linter/linter-format.d.ts +65 -0
  76. package/linter/linter-format.js +9 -0
  77. package/linter/linter-rules.d.ts +42 -0
  78. package/linter/linter-rules.js +14 -0
  79. package/linter/rules/1-deprecated-functions.d.ts +34 -0
  80. package/linter/rules/1-deprecated-functions.js +54 -0
  81. package/linter/rules/2-file-path-validity.d.ts +48 -0
  82. package/linter/rules/2-file-path-validity.js +93 -0
  83. package/package.json +2 -1
  84. package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
  85. package/queries/catalog/call-context-query/call-context-query-format.d.ts +2 -2
  86. package/queries/catalog/call-context-query/call-context-query-format.js +5 -1
  87. package/queries/catalog/cluster-query/cluster-query-format.d.ts +2 -0
  88. package/queries/catalog/cluster-query/cluster-query-format.js +5 -1
  89. package/queries/catalog/config-query/config-query-format.d.ts +1 -0
  90. package/queries/catalog/config-query/config-query-format.js +2 -1
  91. package/queries/catalog/control-flow-query/control-flow-query-executor.d.ts +3 -0
  92. package/queries/catalog/control-flow-query/control-flow-query-executor.js +20 -0
  93. package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +81 -0
  94. package/queries/catalog/control-flow-query/control-flow-query-format.js +34 -0
  95. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -0
  96. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +2 -1
  97. package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +2 -0
  98. package/queries/catalog/dataflow-query/dataflow-query-format.js +9 -1
  99. package/queries/catalog/dependencies-query/dependencies-query-executor.js +33 -32
  100. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -0
  101. package/queries/catalog/dependencies-query/dependencies-query-format.js +10 -1
  102. package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -0
  103. package/queries/catalog/happens-before-query/happens-before-query-format.js +2 -1
  104. package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -0
  105. package/queries/catalog/id-map-query/id-map-query-format.js +2 -1
  106. package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -0
  107. package/queries/catalog/lineage-query/lineage-query-format.js +5 -1
  108. package/queries/catalog/linter-query/linter-query-executor.d.ts +3 -0
  109. package/queries/catalog/linter-query/linter-query-executor.js +28 -0
  110. package/queries/catalog/linter-query/linter-query-format.d.ts +80 -0
  111. package/queries/catalog/linter-query/linter-query-format.js +44 -0
  112. package/queries/catalog/location-map-query/location-map-query-format.d.ts +1 -0
  113. package/queries/catalog/location-map-query/location-map-query-format.js +2 -1
  114. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -0
  115. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +2 -1
  116. package/queries/catalog/origin-query/origin-query-format.d.ts +2 -0
  117. package/queries/catalog/origin-query/origin-query-format.js +5 -1
  118. package/queries/catalog/project-query/project-query-executor.js +1 -1
  119. package/queries/catalog/project-query/project-query-format.d.ts +1 -0
  120. package/queries/catalog/project-query/project-query-format.js +2 -1
  121. package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +3 -3
  122. package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +3 -1
  123. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +4 -23
  124. package/queries/catalog/search-query/search-query-format.d.ts +1 -0
  125. package/queries/catalog/search-query/search-query-format.js +5 -1
  126. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +2 -0
  127. package/queries/catalog/static-slice-query/static-slice-query-format.js +9 -1
  128. package/queries/query.d.ts +143 -1
  129. package/queries/query.js +4 -0
  130. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +11 -4
  131. package/r-bridge/retriever.js +1 -1
  132. package/search/flowr-search-builder.d.ts +31 -2
  133. package/search/flowr-search-builder.js +30 -0
  134. package/search/flowr-search.d.ts +7 -1
  135. package/search/search-executor/search-enrichers.d.ts +73 -0
  136. package/search/search-executor/search-enrichers.js +101 -0
  137. package/search/search-executor/search-generators.d.ts +6 -1
  138. package/search/search-executor/search-generators.js +21 -1
  139. package/search/search-executor/search-mappers.d.ts +19 -0
  140. package/search/search-executor/search-mappers.js +21 -0
  141. package/search/search-executor/search-transformer.d.ts +12 -0
  142. package/search/search-executor/search-transformer.js +11 -1
  143. package/slicing/criterion/parse.d.ts +8 -0
  144. package/slicing/criterion/parse.js +20 -0
  145. package/util/version.js +1 -1
@@ -23,9 +23,12 @@ const log_1 = require("../../../../../../util/log");
23
23
  const fs_1 = __importDefault(require("fs"));
24
24
  const parser_1 = require("../../../../../../r-bridge/lang-4.x/ast/parser/json/parser");
25
25
  const shell_executor_1 = require("../../../../../../r-bridge/shell-executor");
26
- const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
27
26
  const assert_1 = require("../../../../../../util/assert");
28
27
  const path_1 = __importDefault(require("path"));
28
+ const general_1 = require("../../../../../eval/values/general");
29
+ const r_value_1 = require("../../../../../eval/values/r-value");
30
+ const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
31
+ const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
29
32
  let sourceProvider = (0, retriever_1.requestProviderFromFile)();
30
33
  function setSourceProvider(provider) {
31
34
  sourceProvider = provider;
@@ -128,7 +131,7 @@ function processSourceCall(name, args, rootId, data, config) {
128
131
  const sourceFileArgument = args[0];
129
132
  if (!config.forceFollow && (0, config_1.getConfig)().ignoreSourceCalls) {
130
133
  (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping source call ${JSON.stringify(sourceFileArgument)} (disabled in config file)`);
131
- information.graph.markIdForUnknownSideEffects(rootId);
134
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
132
135
  return information;
133
136
  }
134
137
  let sourceFile;
@@ -136,14 +139,8 @@ function processSourceCall(name, args, rootId, data, config) {
136
139
  sourceFile = [(0, retriever_1.removeRQuotes)(sourceFileArgument.lexeme)];
137
140
  }
138
141
  else if (sourceFileArgument !== r_function_call_1.EmptyArgument) {
139
- sourceFile = (0, resolve_by_name_1.resolveValueOfVariable)(sourceFileArgument.value?.lexeme, data.environment, data.completeAst.idMap)?.map(x => {
140
- if (typeof x === 'object' && x && 'str' in x) {
141
- return x.str;
142
- }
143
- else {
144
- return undefined;
145
- }
146
- }).filter(assert_1.isNotUndefined);
142
+ const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(sourceFileArgument.info.id, { environment: data.environment, idMap: data.completeAst.idMap }));
143
+ sourceFile = resolved?.elements.map(r => r.type === 'string' && (0, r_value_1.isValue)(r.value) ? r.value.str : undefined).filter(assert_1.isNotUndefined);
147
144
  }
148
145
  if (sourceFile && sourceFile.length === 1) {
149
146
  const path = (0, retriever_1.removeRQuotes)(sourceFile[0]);
@@ -158,14 +155,14 @@ function processSourceCall(name, args, rootId, data, config) {
158
155
  const findCount = data.referenceChain.filter(e => e.request === request.request && e.content === request.content).length;
159
156
  if (findCount > limit) {
160
157
  logger_1.dataflowLogger.warn(`Found cycle (>=${limit + 1}) in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
161
- information.graph.markIdForUnknownSideEffects(rootId);
158
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
162
159
  return information;
163
160
  }
164
161
  return sourceRequest(rootId, request, data, information, (0, decorate_1.sourcedDeterministicCountingIdGenerator)((findCount > 0 ? findCount + '::' : '') + path, name.location));
165
162
  }
166
163
  }
167
164
  (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Non-constant argument ${JSON.stringify(sourceFile)} for source is currently not supported, skipping`);
168
- information.graph.markIdForUnknownSideEffects(rootId);
165
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
169
166
  return information;
170
167
  }
171
168
  function sourceRequest(rootId, request, data, information, getId) {
@@ -173,7 +170,7 @@ function sourceRequest(rootId, request, data, information, getId) {
173
170
  /* check if the file exists and if not, fail */
174
171
  if (!fs_1.default.existsSync(request.content)) {
175
172
  logger_1.dataflowLogger.warn(`Failed to analyze sourced file ${JSON.stringify(request)}: file does not exist`);
176
- information.graph.markIdForUnknownSideEffects(rootId);
173
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
177
174
  return information;
178
175
  }
179
176
  }
@@ -195,7 +192,7 @@ function sourceRequest(rootId, request, data, information, getId) {
195
192
  catch (e) {
196
193
  logger_1.dataflowLogger.error(`Failed to analyze sourced file ${JSON.stringify(request)}, skipping: ${e.message}`);
197
194
  logger_1.dataflowLogger.error(e.stack);
198
- information.graph.markIdForUnknownSideEffects(rootId);
195
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
199
196
  return information;
200
197
  }
201
198
  // take the entry point as well as all the written references, and give them a control dependency to the source call to show that they are conditional
@@ -229,7 +226,7 @@ function standaloneSourceFile(inputRequest, data, uniqueSourceId, information) {
229
226
  // check if the sourced file has already been dataflow analyzed, and if so, skip it
230
227
  if (data.referenceChain.find(e => e.request === request.request && e.content === request.content)) {
231
228
  logger_1.dataflowLogger.info(`Found loop in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
232
- information.graph.markIdForUnknownSideEffects(uniqueSourceId);
229
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, uniqueSourceId);
233
230
  return information;
234
231
  }
235
232
  return sourceRequest(uniqueSourceId, request, {
@@ -11,6 +11,8 @@ const logger_1 = require("../../../../../logger");
11
11
  const environment_1 = require("../../../../../environments/environment");
12
12
  const edge_1 = require("../../../../../graph/edge");
13
13
  const identifier_1 = require("../../../../../environments/identifier");
14
+ const general_1 = require("../../../../../eval/values/general");
15
+ const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
14
16
  function processWhileLoop(name, args, rootId, data) {
15
17
  if (args.length !== 2 || args[1] === r_function_call_1.EmptyArgument) {
16
18
  logger_1.dataflowLogger.warn(`While-Loop ${name.content} does not have 2 arguments, skipping`);
@@ -21,6 +23,13 @@ function processWhileLoop(name, args, rootId, data) {
21
23
  logger_1.dataflowLogger.warn(`While-Loop ${name.content} has empty arguments in ${JSON.stringify(args)}, skipping`);
22
24
  return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
23
25
  }
26
+ // we should defer this to the abstract interpretation
27
+ const values = (0, alias_tracking_1.resolveIdToValue)(unpackedArgs[0]?.info.id, { environment: data.environment, idMap: data.completeAst.idMap });
28
+ const conditionIsAlwaysFalse = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === false) ?? false;
29
+ //We don't care about the body if it never executes
30
+ if (conditionIsAlwaysFalse) {
31
+ unpackedArgs.pop();
32
+ }
24
33
  /* we inject the cf-dependency of the while-loop after the condition */
25
34
  const { information, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({
26
35
  name,
@@ -36,10 +45,24 @@ function processWhileLoop(name, args, rootId, data) {
36
45
  }, origin: 'builtin:while-loop'
37
46
  });
38
47
  const [condition, body] = processedArguments;
48
+ // If the condition is always false, we don't include the body
49
+ if (condition !== undefined && conditionIsAlwaysFalse) {
50
+ information.graph.addEdge(name.info.id, condition.entryPoint, edge_1.EdgeType.Reads);
51
+ return {
52
+ unknownReferences: [],
53
+ in: [{ nodeId: name.info.id, name: name.lexeme, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function }],
54
+ out: condition.out,
55
+ entryPoint: name.info.id,
56
+ exitPoints: [],
57
+ graph: information.graph,
58
+ environment: information.environment
59
+ };
60
+ }
39
61
  (0, assert_1.guard)(condition !== undefined && body !== undefined, () => `While-Loop ${name.content} has no condition or body, impossible!`);
40
62
  const originalDependency = data.controlDependencies;
41
63
  if ((0, info_1.alwaysExits)(condition)) {
42
64
  logger_1.dataflowLogger.warn(`While-Loop ${rootId} forces exit in condition, skipping rest`);
65
+ information.graph.addEdge(name.info.id, condition.entryPoint, edge_1.EdgeType.Reads);
43
66
  return condition;
44
67
  }
45
68
  const remainingInputs = (0, linker_1.linkInputs)([
@@ -10,6 +10,7 @@ const edge_1 = require("../../../../graph/edge");
10
10
  const logger_1 = require("../../../../logger");
11
11
  const vertex_1 = require("../../../../graph/vertex");
12
12
  const log_1 = require("../../../../../util/log");
13
+ const unknown_side_effect_1 = require("../../../../graph/unknown-side-effect");
13
14
  function markNonStandardEvaluationEdges(markAsNSE, callArgs, finalGraph, rootId) {
14
15
  for (const nse of markAsNSE) {
15
16
  if (nse < callArgs.length) {
@@ -46,7 +47,7 @@ function processKnownFunctionCall({ name, args, rootId, data, reverseOrder = fal
46
47
  origin: origin === 'default' ? ['function'] : [origin]
47
48
  });
48
49
  if (hasUnknownSideEffect) {
49
- finalGraph.markIdForUnknownSideEffects(rootId);
50
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(finalGraph, data.environment, rootId);
50
51
  }
51
52
  const inIds = remainingReadInArgs;
52
53
  const fnRef = { nodeId: rootId, name: functionCallName, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function };
@@ -19,5 +19,5 @@ export interface PrintCfgOptions {
19
19
  readonly simplify?: boolean;
20
20
  readonly useDfg?: boolean;
21
21
  }
22
- export declare function printCFGCode(parser: KnownParser, code: string, { showCode, openCode, prefix, simplifications, simplify, useDfg }?: PrintCfgOptions): Promise<string>;
22
+ export declare function printCfgCode(parser: KnownParser, code: string, { showCode, openCode, prefix, simplifications, simplify, useDfg }?: PrintCfgOptions): Promise<string>;
23
23
  export {};
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCfg = getCfg;
4
4
  exports.printCfg = printCfg;
5
- exports.printCFGCode = printCFGCode;
5
+ exports.printCfgCode = printCfgCode;
6
6
  const extract_cfg_1 = require("../../control-flow/extract-cfg");
7
7
  const default_pipelines_1 = require("../../core/steps/pipeline/default-pipelines");
8
8
  const retriever_1 = require("../../r-bridge/retriever");
@@ -17,7 +17,7 @@ async function getCfg(parser, code, simplifications = [], useDfg = true) {
17
17
  }).allRemainingSteps() : await (0, default_pipelines_1.createNormalizePipeline)(parser, {
18
18
  request: (0, retriever_1.requestFromInput)(code)
19
19
  }).allRemainingSteps();
20
- const cfg = (0, extract_cfg_1.extractCFG)(result.normalize, useDfg ? result.dataflow.graph : undefined, [...cfg_simplification_1.DefaultCfgSimplificationOrder, ...simplifications]);
20
+ const cfg = (0, extract_cfg_1.extractCfg)(result.normalize, useDfg ? result.dataflow.graph : undefined, [...cfg_simplification_1.DefaultCfgSimplificationOrder, ...simplifications]);
21
21
  return {
22
22
  info: cfg,
23
23
  ast: result.normalize,
@@ -29,7 +29,7 @@ function printCfg(cfg, ast, prefix = 'flowchart BT\n', simplify = false) {
29
29
  ${(0, doc_code_1.codeBlock)('mermaid', (0, cfg_1.cfgToMermaid)(cfg, ast, prefix, simplify))}
30
30
  `;
31
31
  }
32
- async function printCFGCode(parser, code, { showCode = true, openCode = false, prefix = 'flowchart BT\n', simplifications = [], simplify = false, useDfg = true } = {}) {
32
+ async function printCfgCode(parser, code, { showCode = true, openCode = false, prefix = 'flowchart BT\n', simplifications = [], simplify = false, useDfg = true } = {}) {
33
33
  const now = performance.now();
34
34
  const res = await getCfg(parser, code, simplifications, useDfg);
35
35
  const duration = performance.now() - now;
@@ -1,13 +1,16 @@
1
1
  import type { RShell } from '../../r-bridge/shell';
2
- import type { Queries, SupportedQueryTypes } from '../../queries/query';
2
+ import type { Queries, QueryResults, SupportedQueryTypes } from '../../queries/query';
3
+ import { DEFAULT_DATAFLOW_PIPELINE } from '../../core/steps/pipeline/default-pipelines';
3
4
  import type { SupportedVirtualQueryTypes } from '../../queries/virtual-query/virtual-queries';
4
5
  import type { VirtualCompoundConstraint } from '../../queries/virtual-query/compound-query';
5
- export interface ShowQueryOptions {
6
+ import type { PipelineOutput } from '../../core/steps/pipeline/pipeline';
7
+ export interface ShowQueryOptions<Base extends SupportedQueryTypes> {
6
8
  readonly showCode?: boolean;
7
9
  readonly collapseResult?: boolean;
8
10
  readonly collapseQuery?: boolean;
11
+ readonly addOutput?: (result: QueryResults<Base>, pipeline: PipelineOutput<typeof DEFAULT_DATAFLOW_PIPELINE>) => string;
9
12
  }
10
- export declare function showQuery<Base extends SupportedQueryTypes, VirtualArguments extends VirtualCompoundConstraint<Base> = VirtualCompoundConstraint<Base>>(shell: RShell, code: string, queries: Queries<Base, VirtualArguments>, { showCode, collapseResult, collapseQuery }?: ShowQueryOptions): Promise<string>;
13
+ export declare function showQuery<Base extends SupportedQueryTypes, VirtualArguments extends VirtualCompoundConstraint<Base> = VirtualCompoundConstraint<Base>>(shell: RShell, code: string, queries: Queries<Base, VirtualArguments>, { showCode, collapseResult, collapseQuery, addOutput }?: ShowQueryOptions<Base>): Promise<string>;
11
14
  export interface QueryDocumentation {
12
15
  readonly name: string;
13
16
  readonly type: 'virtual' | 'active';
@@ -17,7 +17,7 @@ const doc_dfg_1 = require("./doc-dfg");
17
17
  const doc_code_1 = require("./doc-code");
18
18
  const time_1 = require("../../util/text/time");
19
19
  const query_print_1 = require("../../queries/query-print");
20
- async function showQuery(shell, code, queries, { showCode, collapseResult, collapseQuery } = {}) {
20
+ async function showQuery(shell, code, queries, { showCode, collapseResult, collapseQuery, addOutput = () => '' } = {}) {
21
21
  const now = performance.now();
22
22
  const analysis = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
23
23
  parser: shell,
@@ -60,6 +60,8 @@ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { switchCodeAndGraph: tr
60
60
 
61
61
  ${collapseResult ? '</details>' : ''}
62
62
 
63
+ ${addOutput(results, analysis)}
64
+
63
65
  `;
64
66
  }
65
67
  exports.RegisteredQueries = {
@@ -89,10 +89,10 @@ class CollectNumbersSyntaxVisitor extends syntax_cfg_guided_visitor_1.SyntaxAwar
89
89
  class CollectNumbersDataflowVisitor extends dfg_cfg_guided_visitor_1.DataflowAwareCfgGuidedVisitor {
90
90
  numbers = [];
91
91
  constructor(controlFlow, dataflow) {
92
- super({ controlFlow, dataflow, defaultVisitingOrder: 'forward' });
92
+ super({ controlFlow, dfg: dataflow, defaultVisitingOrder: 'forward' });
93
93
  }
94
94
  visitValue(node) {
95
- const astNode = this.config.dataflow.graph.idMap?.get(node.id);
95
+ const astNode = this.config.dfg.idMap?.get(node.id);
96
96
  if ((0, r_number_1.isRNumber)(astNode)) {
97
97
  this.numbers.push(astNode.content);
98
98
  }
@@ -104,7 +104,7 @@ class CollectNumbersDataflowVisitor extends dfg_cfg_guided_visitor_1.DataflowAwa
104
104
  class CollectSourcesSemanticVisitor extends semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor {
105
105
  sources = [];
106
106
  constructor(controlFlow, normalizedAst, dataflow) {
107
- super({ controlFlow, normalizedAst, dataflow, defaultVisitingOrder: 'forward' });
107
+ super({ controlFlow, normalizedAst, dfg: dataflow, defaultVisitingOrder: 'forward' });
108
108
  }
109
109
  onAssignmentCall({ source }) {
110
110
  if (source) {
@@ -167,7 +167,7 @@ ${(0, doc_code_1.codeBlock)('r', 'x <- 2 * 3 + 1')}
167
167
 
168
168
  The corresponding CFG is a directed, labeled graph with two types of edges (control and flow dependencies).
169
169
 
170
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'x <- 2 * 3 + 1', { showCode: false, prefix: 'flowchart RL\n' })}
170
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'x <- 2 * 3 + 1', { showCode: false, prefix: 'flowchart RL\n' })}
171
171
 
172
172
  ${(0, doc_structure_1.block)({
173
173
  type: 'IMPORTANT',
@@ -180,33 +180,33 @@ Expressions, such as \`2 * 3\` get an additional node with an artificial id that
180
180
 
181
181
  To gain a better understanding, let's have a look at a simple program with a single branching structure:
182
182
 
183
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'if(u) 3 else 2', { showCode: true, openCode: false, prefix: 'flowchart RL\n' })}
183
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'if(u) 3 else 2', { showCode: true, openCode: false, prefix: 'flowchart RL\n' })}
184
184
 
185
185
  Here, you can see the \`if\` node followed by the condition (in this case merely \`u\`) that then splits into two branches for the two possible outcomes.
186
186
  The \`if\` structure is terminated by the corresponding \`-exit\` node (see the [structure](#cfg-structure) section for more details).
187
187
 
188
188
  For you to compare, the following shows the CFG of an \`if\` without an \`else\` branch:
189
189
 
190
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'if(u || v) 3', { showCode: true, openCode: false, prefix: 'flowchart RL\n' })}
190
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'if(u || v) 3', { showCode: true, openCode: false, prefix: 'flowchart RL\n' })}
191
191
 
192
192
  Activating the calculation of basic blocks produces the following:
193
193
 
194
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'if(u || v) 3', { showCode: true, openCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'] })}
194
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'if(u || v) 3', { showCode: true, openCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'] })}
195
195
 
196
196
  Which is probably much more readable if compacted (although the reconstucted code can sometimes be slightly mislieading as flowR tries its best to make it syntactically correct and hence add closing braces etc. which are technically not part of the respective block):
197
197
 
198
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'if(u || v) 3', { showCode: true, openCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'], simplify: true })}
198
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'if(u || v) 3', { showCode: true, openCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'], simplify: true })}
199
199
 
200
200
  The control flow graph also harmonizes with function definitions, and calls:
201
201
 
202
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'f <- function() { 3 }\nf()', { showCode: true, openCode: true, prefix: 'flowchart RL\n' })}
202
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'f <- function() { 3 }\nf()', { showCode: true, openCode: true, prefix: 'flowchart RL\n' })}
203
203
 
204
204
  ${(0, doc_structure_1.section)('Structure of the Control Flow Graph', 2, 'cfg-structure')}
205
205
 
206
- You can produce your very own control flow graph with ${(0, doc_types_1.shortLink)(extract_cfg_1.extractCFG.name, types.info)}.
206
+ You can produce your very own control flow graph with ${(0, doc_types_1.shortLink)(extract_cfg_1.extractCfg.name, types.info)}.
207
207
  The ${(0, doc_types_1.shortLink)(control_flow_graph_1.ControlFlowGraph.name, types.info)} class describes everything required to model the control flow graph, with its edge types described by
208
208
  ${(0, doc_types_1.shortLink)('CfgEdge', types.info)} and its vertices by ${(0, doc_types_1.shortLink)('CfgSimpleVertex', types.info)}.
209
- However, you should be aware of the ${(0, doc_types_1.shortLink)('ControlFlowInformation', types.info)} interface which adds some additional information the the CFG
209
+ However, you should be aware of the ${(0, doc_types_1.shortLink)('ControlFlowInformation', types.info)} interface which adds some additional information the CFG
210
210
  (and is used during the construction of the CFG as well):
211
211
 
212
212
  ${(0, doc_types_1.printHierarchy)({ info: types.info, root: 'ControlFlowInformation', program: types.program, openTop: true })}
@@ -214,7 +214,7 @@ ${(0, doc_types_1.printHierarchy)({ info: types.info, root: 'ControlFlowInformat
214
214
  To check whether the CFG has the expected shape, you can use the test function ${(0, doc_types_1.shortLink)('assertCfg', testTypes.info)} which supports testing for
215
215
  sub-graphs as well (it provides diffing capabilities similar to ${(0, doc_types_1.shortLink)('assertDataflow', testTypes.info)}).
216
216
  As the CFG may become unhandy for larger programs, there are simplifications available with ${(0, doc_types_1.shortLink)(cfg_simplification_1.simplifyControlFlowInformation.name, types.info)}
217
- (these can be passed on to the ${(0, doc_types_1.shortLink)(extract_cfg_1.extractCFG.name, types.info)} function as well).
217
+ (these can be passed on to the ${(0, doc_types_1.shortLink)(extract_cfg_1.extractCfg.name, types.info)} function as well).
218
218
 
219
219
  ${(0, doc_structure_1.section)('CFG Vertices', 3, 'cfg-structure-vertices')}
220
220
 
@@ -258,7 +258,7 @@ ${(0, doc_structure_1.section)('Flow Dependencies', 4, 'cfg-flow-dependency')}
258
258
  The most common edge is the flow dependency&nbsp;(FD) which simply signals that the source vertex happens _after_ the target vertex in the control flow.
259
259
  So \`x; y\` would produce a flow dependency from \`y\` to \`x\` (additionally to the program-enveloping root expression list):
260
260
 
261
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'x; y', { showCode: false, prefix: 'flowchart RL\n' })}
261
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'x; y', { showCode: false, prefix: 'flowchart RL\n' })}
262
262
 
263
263
  ${(0, doc_structure_1.section)('Control Dependencies', 4, 'cfg-control-dependency')}
264
264
 
@@ -271,12 +271,12 @@ The extra \`caused\` link signals the vertex that caused the control flow influe
271
271
 
272
272
 
273
273
  ${await (async () => {
274
- const exa = await (0, doc_cfg_1.printCFGCode)(shell, 'if(u) 3 else 2', { showCode: true, prefix: 'flowchart RL\n' });
274
+ const exa = await (0, doc_cfg_1.printCfgCode)(shell, 'if(u) 3 else 2', { showCode: true, prefix: 'flowchart RL\n' });
275
275
  return (0, doc_structure_1.details)('Example: if-else', exa);
276
276
  })()}
277
277
 
278
278
  ${await (async () => {
279
- const exa = await (0, doc_cfg_1.printCFGCode)(shell, 'while(u) b', { showCode: true, prefix: 'flowchart RL\n' });
279
+ const exa = await (0, doc_cfg_1.printCfgCode)(shell, 'while(u) b', { showCode: true, prefix: 'flowchart RL\n' });
280
280
  return (0, doc_structure_1.details)('Example: while-loop', exa);
281
281
  })()}
282
282
  <br/>
@@ -286,12 +286,12 @@ Additionally, the control flow graph does not have to be connected. If you use a
286
286
  the corresponding exit markers are not reachable from the entry:
287
287
 
288
288
  ${await (async () => {
289
- const exa = await (0, doc_cfg_1.printCFGCode)(shell, 'repeat { b }; after', { showCode: true, prefix: 'flowchart RL\n' });
289
+ const exa = await (0, doc_cfg_1.printCfgCode)(shell, 'repeat { b }; after', { showCode: true, prefix: 'flowchart RL\n' });
290
290
  return (0, doc_structure_1.details)('Example: repeat-loop (infinite)', exa);
291
291
  })()}
292
292
 
293
293
  ${await (async () => {
294
- const exa = await (0, doc_cfg_1.printCFGCode)(shell, 'repeat { b; if(u) break; }; after', { showCode: true, prefix: 'flowchart RL\n' });
294
+ const exa = await (0, doc_cfg_1.printCfgCode)(shell, 'repeat { b; if(u) break; }; after', { showCode: true, prefix: 'flowchart RL\n' });
295
295
  return (0, doc_structure_1.details)('Example: repeat-loop (with break)', exa);
296
296
  })()}
297
297
  <br/>
@@ -299,22 +299,22 @@ ${await (async () => {
299
299
  In the context of a for-loop, the control dependency refer to whether the respective vector still has values to iterate over.
300
300
 
301
301
  ${await (async () => {
302
- const exa = await (0, doc_cfg_1.printCFGCode)(shell, 'for(i in 1:10) b', { showCode: true, prefix: 'flowchart RL\n' });
302
+ const exa = await (0, doc_cfg_1.printCfgCode)(shell, 'for(i in 1:10) b', { showCode: true, prefix: 'flowchart RL\n' });
303
303
  return (0, doc_structure_1.details)('Example: for-loop', exa);
304
304
  })()}
305
305
 
306
306
  ${(0, doc_structure_1.section)('Extra: Call Links', 4, 'cfg-call-links')}
307
307
 
308
- If you generate the CFG with the ${(0, doc_types_1.shortLink)(extract_cfg_1.extractCFG.name, types.info)} function you can (and, if you want to gain inter-procedural information, should)
308
+ If you generate the CFG with the ${(0, doc_types_1.shortLink)(extract_cfg_1.extractCfg.name, types.info)} function you can (and, if you want to gain inter-procedural information, should)
309
309
  pass a matching [dataflow graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph) to it to incorporate the dataflow perspective into the CFG.
310
310
 
311
311
  The difference becomes obvious when we look at the code \`f <- function() b; f()\` first without the dataflow graph:
312
312
 
313
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'f <- function() b; f()', { showCode: true, prefix: 'flowchart RL\n', useDfg: false })}
313
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'f <- function() b; f()', { showCode: true, prefix: 'flowchart RL\n', useDfg: false })}
314
314
 
315
315
  And now, including dataflow information:
316
316
 
317
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'f <- function() b; f()', { showCode: true, prefix: 'flowchart RL\n', useDfg: true })}
317
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'f <- function() b; f()', { showCode: true, prefix: 'flowchart RL\n', useDfg: true })}
318
318
 
319
319
  There are two important additions:
320
320
 
@@ -325,7 +325,7 @@ There are two important additions:
325
325
  For built-in functions that are provided by flowR's built-in configuration (see the [interface wiki page](${doc_files_1.FlowrWikiBaseRef}/Interface)) the CFG does not contain
326
326
  the additional information directly:
327
327
 
328
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'print(3)', { showCode: true, prefix: 'flowchart RL\n' })}
328
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'print(3)', { showCode: true, prefix: 'flowchart RL\n' })}
329
329
 
330
330
  This is due to the fact that the [dataflow graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph) does contain the required call information (and there are no new control vertices to add as the built-in call has no target in the source code):
331
331
 
@@ -340,16 +340,16 @@ Yet, we can request basic blocks or transform an existing CFG into basic blocks
340
340
 
341
341
  Any program without any (un-)conditional jumps now contains a single basic block:
342
342
 
343
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'x <- 2 * 3 + 1', { showCode: true, openCode: true, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'], simplify: true })}
343
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'x <- 2 * 3 + 1', { showCode: true, openCode: true, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'], simplify: true })}
344
344
 
345
345
  While the CFG without basic blocks is much bigger:
346
346
 
347
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'x <- 2 * 3 + 1', { showCode: false, prefix: 'flowchart RL\n' })}
347
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'x <- 2 * 3 + 1', { showCode: false, prefix: 'flowchart RL\n' })}
348
348
 
349
349
  In a way, using the basic blocks perspective does not remove any of these vertices (we just usually visualize them compacted as their execution order should be "obvious").
350
350
  The vertices are still there, as elems of the ${(0, doc_types_1.shortLink)('CfgBasicBlockVertex', types.info)}:
351
351
 
352
- ${await (0, doc_cfg_1.printCFGCode)(shell, 'x <- 2 * 3 + 1', { showCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'], simplify: false })}
352
+ ${await (0, doc_cfg_1.printCfgCode)(shell, 'x <- 2 * 3 + 1', { showCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'], simplify: false })}
353
353
 
354
354
  The benefit (for comprehensibility and algorithms) becomes more apparent when we look at a more complicated program:
355
355
 
@@ -357,12 +357,12 @@ ${(0, doc_code_1.codeBlock)('r', CfgLongExample)}
357
357
 
358
358
  With basic blocks, this code looks like this:
359
359
 
360
- ${await (0, doc_cfg_1.printCFGCode)(shell, CfgLongExample, { showCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'], simplify: true })}
360
+ ${await (0, doc_cfg_1.printCfgCode)(shell, CfgLongExample, { showCode: false, prefix: 'flowchart RL\n', simplifications: ['to-basic-blocks'], simplify: true })}
361
361
 
362
362
  Now, without basic blocks, this is a different story...
363
363
 
364
364
  ${await (async () => {
365
- const exa = await (0, doc_cfg_1.printCFGCode)(shell, CfgLongExample, { showCode: false, prefix: 'flowchart RL\n' });
365
+ const exa = await (0, doc_cfg_1.printCfgCode)(shell, CfgLongExample, { showCode: false, prefix: 'flowchart RL\n' });
366
366
  return (0, doc_structure_1.details)('The full CFG', exa);
367
367
  })()}
368
368
 
@@ -475,7 +475,7 @@ Again, executing it with the CFG and Dataflow of the expression \`x - 1 + 2L * 3
475
475
 
476
476
  ${await (async () => {
477
477
  const res = await (0, doc_cfg_1.getCfg)(shell, 'x - 1 + 2L * 3');
478
- const visitor = new CollectNumbersDataflowVisitor(res.info, res.dataflow);
478
+ const visitor = new CollectNumbersDataflowVisitor(res.info, res.dataflow.graph);
479
479
  visitor.start();
480
480
  const collected = visitor.getNumbers();
481
481
  return collected.map(n => '\n- `' + JSON.stringify(n) + '`').join('');
@@ -500,7 +500,7 @@ Executing it with the CFG and Dataflow of the expression \`x <- 2; 3 -> x; assig
500
500
 
501
501
  ${await (async () => {
502
502
  const res = await (0, doc_cfg_1.getCfg)(shell, 'x <- 2; 3 -> x; assign("x", 42 + 21)');
503
- const visitor = new CollectSourcesSemanticVisitor(res.info, res.ast, res.dataflow);
503
+ const visitor = new CollectSourcesSemanticVisitor(res.info, res.ast, res.dataflow.graph);
504
504
  visitor.start();
505
505
  const collected = visitor.getSources();
506
506
  return collected.map(n => '\n- `' + n + '`').join('');
@@ -529,7 +529,7 @@ ${await (async function () {
529
529
  (0, assert_1.guard)(plusVertex.type === control_flow_graph_1.CfgVertexType.Expression);
530
530
  const numOfExits = plusVertex.end?.length ?? 0;
531
531
  (0, assert_1.guard)(plusVertex.end && numOfExits === 1);
532
- return `${await (0, doc_cfg_1.printCFGCode)(shell, 'x + 1', { showCode: true, prefix: 'flowchart RL\n' })}
532
+ return `${await (0, doc_cfg_1.printCfgCode)(shell, 'x + 1', { showCode: true, prefix: 'flowchart RL\n' })}
533
533
 
534
534
  Looking at the binary operation vertex for \`+\` (with id \`${plusVertexId}\`) we see that it is linked to a single exit ("end marker") point: \`${plusVertex.end[0]}\`.
535
535
  Checking this vertex essentially reveals all exit points of the expression &dash; in this case, this simply refers to the operands of the addition.
@@ -544,7 +544,7 @@ ${(0, doc_structure_1.details)('Example: Exit Points for an if', await (async fu
544
544
  (0, assert_1.guard)(ifVertex.type === control_flow_graph_1.CfgVertexType.Statement);
545
545
  const numOfExits = ifVertex.end?.length ?? 0;
546
546
  (0, assert_1.guard)(ifVertex.end && numOfExits === 1);
547
- return `${await (0, doc_cfg_1.printCFGCode)(shell, expr, { showCode: true, prefix: 'flowchart RL\n' })}
547
+ return `${await (0, doc_cfg_1.printCfgCode)(shell, expr, { showCode: true, prefix: 'flowchart RL\n' })}
548
548
 
549
549
  Looking at the if vertex for (with id \`${ifVertexId}\`) we see that it is again linked to a single exit point: \`${ifVertex.end[0]}\`.
550
550
  Yet, now this exit vertex is linked to the two branches of the if statement (the \`then\` and \`else\` branch).
@@ -34,6 +34,7 @@ const linker_1 = require("../dataflow/internal/linker");
34
34
  const doc_normalized_ast_1 = require("./doc-util/doc-normalized-ast");
35
35
  const dfg_get_origin_1 = require("../dataflow/origin/dfg-get-origin");
36
36
  const identify_link_to_last_call_relation_1 = require("../queries/catalog/call-context-query/identify-link-to-last-call-relation");
37
+ const alias_tracking_1 = require("../dataflow/eval/resolve/alias-tracking");
37
38
  const doc_issue_1 = require("./doc-util/doc-issue");
38
39
  const unnamed_call_handling_1 = require("../dataflow/internal/process/functions/call/unnamed-call-handling");
39
40
  const environment_builder_1 = require("../../test/functionality/_helper/dataflow/environment-builder");
@@ -977,7 +978,7 @@ Depending on what you are interested in, there exists a plethora of functions an
977
978
  * The **[Query API](${doc_files_1.FlowrWikiBaseRef}/Query%20API)** provides many functions to query the dataflow graph for specific information (dependencies, calls, slices, clusters, ...)
978
979
  * The **[Search API](${doc_files_1.FlowrWikiBaseRef}/Search%20API)** allows you to search for specific vertices or edges in the dataflow graph or the original program
979
980
  * ${(0, doc_types_1.shortLink)(node_id_1.recoverName.name, vertexType.info)} and ${(0, doc_types_1.shortLink)(node_id_1.recoverContent.name, vertexType.info)} to get the name or content of a vertex in the dataflow graph
980
- * ${(0, doc_types_1.shortLink)(resolve_by_name_1.resolveValueOfVariable.name, vertexType.info)} and ${(0, doc_types_1.shortLink)(resolve_by_name_1.resolveIdToValue.name, vertexType.info)} to resolve the value of a variable or id (if possible, see [below](#dfg-resolving-values))
981
+ * ${(0, doc_types_1.shortLink)(alias_tracking_1.resolveIdToValue.name, vertexType.info)} to resolve the value of a variable or id (if possible, see [below](#dfg-resolving-values))
981
982
  * ${(0, doc_types_1.shortLink)(edge_1.edgeIncludesType.name, vertexType.info)} to check if an edge includes a specific type and ${(0, doc_types_1.shortLink)(edge_1.splitEdgeTypes.name, vertexType.info)} to split the bitmask of edges into its types (see [below](#dfg-resolving-values))
982
983
  * ${(0, doc_types_1.shortLink)(identify_link_to_last_call_relation_1.getValueOfArgument.name, vertexType.info)} to get the (syntactical) value of an argument in a function call
983
984
  * ${(0, doc_types_1.shortLink)(dfg_get_origin_1.getOriginInDfg.name, vertexType.info)} to get information about where a read, call, ... comes from (see [below](#dfg-resolving-values))
@@ -989,8 +990,8 @@ ${(0, doc_structure_1.section)('Resolving Values', 3, 'dfg-resolving-values')}
989
990
  FlowR supports a [configurable](${doc_files_1.FlowrWikiBaseRef}/Interface#configuring-flowr) level of value tracking&mdash;all with the goal of knowing the static value domain of a variable.
990
991
  These capabilities are exposed by the [resolve value Query](${doc_files_1.FlowrWikiBaseRef}/Query-API#resolve-value-query) and backed by two important functions:
991
992
 
992
- ${(0, doc_types_1.shortLink)(resolve_by_name_1.resolveValueOfVariable.name, vertexType.info)} provides an environment-sensitive (see ${(0, doc_types_1.shortLink)('REnvironmentInformation', vertexType.info)})
993
- value resolution, while ${(0, doc_types_1.shortLink)(resolve_by_name_1.resolveIdToValue.name, vertexType.info)} provides a more general, but potentially less precise resolution independent of the current state.
993
+ ${(0, doc_types_1.shortLink)(alias_tracking_1.resolveIdToValue.name, vertexType.info)} provides an environment-sensitive (see ${(0, doc_types_1.shortLink)('REnvironmentInformation', vertexType.info)})
994
+ value resolution depending on if the environment is provided.
994
995
 
995
996
  ${(0, doc_structure_1.section)('Assessing Edges', 3, 'dfg-assess-edge')}
996
997
 
@@ -49,7 +49,7 @@ are exposed with some command line options (e.g., when using the docker image of
49
49
 
50
50
  ${(0, doc_structure_1.block)({
51
51
  type: 'WARNING',
52
- content: 'As the tree-sitter engine is only for parsing, it cannot execute R code.'
52
+ content: 'As the tree-sitter engine is only for parsing, it cannot execute R code. This engine is now the default.'
53
53
  })}
54
54
 
55
55
  In general, there is no need for you to pass custom paths using either
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,76 @@
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
+ const log_1 = require("../../test/functionality/_helper/log");
7
+ const doc_auto_gen_1 = require("./doc-util/doc-auto-gen");
8
+ const doc_files_1 = require("./doc-util/doc-files");
9
+ const linter_rules_1 = require("../linter/linter-rules");
10
+ const doc_code_1 = require("./doc-util/doc-code");
11
+ const shell_1 = require("../r-bridge/shell");
12
+ const doc_query_1 = require("./doc-util/doc-query");
13
+ const doc_types_1 = require("./doc-util/doc-types");
14
+ const path_1 = __importDefault(require("path"));
15
+ async function getText(shell) {
16
+ const rVersion = (await shell.usedRVersion())?.format() ?? 'unknown';
17
+ return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'linter', rVersion })}
18
+
19
+ This page describes the flowR linter, which is a tool that utilizes flowR's dataflow analysis to find common issues in R scripts. The linter can currently be used through the linter [query](${doc_files_1.FlowrWikiBaseRef}/Query%20API).
20
+
21
+ ## Linting Rules
22
+
23
+ The following linting rules are available:
24
+
25
+ ${await rule(shell, 'deprecated-functions', 'DeprecatedFunctionsConfig', 'Deprecated Functions', 'This rule detects the usage of deprecated functions in code based on a predefined list of known deprecated functions.', `
26
+ first <- data.frame(x = c(1, 2, 3), y = c(1, 2, 3))
27
+ second <- data.frame(x = c(1, 3, 2), y = c(1, 3, 2))
28
+ dplyr::all_equal(first, second)
29
+ `)}
30
+
31
+ ${await rule(shell, 'file-path-validity', 'FilePathValidityConfig', 'File Path Validity', 'This rule finds places in the code where files are being read from. In such places, it checks whether the file path is valid and whether the file exists on disk.', `
32
+ my_data <- read.csv("C:/Users/me/Documents/My R Scripts/Reproducible.csv")
33
+ `)}
34
+
35
+ `.trim();
36
+ }
37
+ async function rule(shell, name, configType, friendlyName, description, example) {
38
+ const types = (0, doc_types_1.getTypesFromFolderAsMermaid)({
39
+ rootFolder: path_1.default.resolve('./src/linter/'),
40
+ typeName: configType,
41
+ inlineTypes: doc_types_1.mermaidHide
42
+ });
43
+ return `
44
+ ### ${friendlyName} (\`${name}\`)
45
+
46
+ ${description}
47
+
48
+ <details>
49
+
50
+ #### Configuration
51
+
52
+ Linting rules can be configured by passing a configuration object to the linter query as shown in the example below. The \`${name}\` rule accepts the following configuration options:
53
+
54
+ ${Object.getOwnPropertyNames(linter_rules_1.LintingRules[name].defaultConfig).sort().map(key => `- ${(0, doc_types_1.shortLink)(`${configType}:::${key}`, types.info)}\\\n${(0, doc_types_1.getDocumentationForType)(`${configType}::${key}`, types.info)}`).join('\n')}
55
+
56
+ #### Example
57
+
58
+ ${(0, doc_code_1.codeBlock)('r', example)}
59
+
60
+ The linting query can be used to run this rule on the above example:
61
+
62
+ ${await (0, doc_query_1.showQuery)(shell, example, [{ type: 'linter', rules: [{ name, config: {} }] }], { collapseQuery: true })}
63
+
64
+ </details>
65
+ `.trim();
66
+ }
67
+ if (require.main === module) {
68
+ (0, log_1.setMinLevelOfAllLogs)(6 /* LogLevel.Fatal */);
69
+ const shell = new shell_1.RShell();
70
+ void getText(shell).then(str => {
71
+ console.log(str);
72
+ }).finally(() => {
73
+ shell.close();
74
+ });
75
+ }
76
+ //# sourceMappingURL=print-linter-wiki.js.map