@eagleoutice/flowr 2.10.3 → 2.10.5

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 (94) hide show
  1. package/README.md +43 -26
  2. package/abstract-interpretation/absint-visitor.d.ts +17 -21
  3. package/abstract-interpretation/absint-visitor.js +47 -48
  4. package/abstract-interpretation/data-frame/dataframe-domain.d.ts +0 -3
  5. package/abstract-interpretation/data-frame/shape-inference.d.ts +2 -1
  6. package/abstract-interpretation/data-frame/shape-inference.js +5 -4
  7. package/abstract-interpretation/domains/abstract-domain.d.ts +17 -16
  8. package/abstract-interpretation/domains/abstract-domain.js +25 -27
  9. package/abstract-interpretation/domains/bounded-set-domain.js +1 -1
  10. package/abstract-interpretation/domains/multi-value-state-domain.d.ts +32 -0
  11. package/abstract-interpretation/domains/multi-value-state-domain.js +60 -0
  12. package/abstract-interpretation/domains/partial-product-domain.d.ts +43 -0
  13. package/abstract-interpretation/domains/partial-product-domain.js +163 -0
  14. package/abstract-interpretation/domains/product-domain.d.ts +2 -29
  15. package/abstract-interpretation/domains/product-domain.js +6 -123
  16. package/abstract-interpretation/domains/set-range-domain.js +3 -3
  17. package/abstract-interpretation/domains/set-upper-bound-domain.js +1 -1
  18. package/abstract-interpretation/domains/singleton-domain.js +1 -1
  19. package/abstract-interpretation/domains/state-abstract-domain.d.ts +13 -28
  20. package/abstract-interpretation/domains/state-abstract-domain.js +16 -38
  21. package/abstract-interpretation/domains/state-domain-like.d.ts +36 -0
  22. package/abstract-interpretation/domains/state-domain-like.js +3 -0
  23. package/cli/flowr.js +11 -1
  24. package/config.d.ts +7 -0
  25. package/config.js +22 -3
  26. package/control-flow/semantic-cfg-guided-visitor.d.ts +4 -0
  27. package/control-flow/semantic-cfg-guided-visitor.js +20 -32
  28. package/dataflow/environments/default-builtin-config.d.ts +10 -0
  29. package/dataflow/environments/default-builtin-config.js +2 -1
  30. package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +2 -0
  31. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +38 -21
  32. package/documentation/doc-readme.js +13 -2
  33. package/documentation/wiki-absint.d.ts +1 -2
  34. package/documentation/wiki-absint.js +34 -10
  35. package/documentation/wiki-analyzer.js +3 -4
  36. package/documentation/wiki-interface.js +21 -16
  37. package/documentation/wiki-linter.js +1 -1
  38. package/linter/linter-rules.d.ts +12 -12
  39. package/linter/linter-rules.js +2 -2
  40. package/linter/rules/network-functions.d.ts +1 -1
  41. package/linter/rules/network-functions.js +8 -2
  42. package/linter/rules/problematic-inputs.d.ts +43 -0
  43. package/linter/rules/problematic-inputs.js +110 -0
  44. package/linter/rules/seeded-randomness.d.ts +1 -1
  45. package/linter/rules/seeded-randomness.js +8 -1
  46. package/package.json +4 -4
  47. package/project/flowr-analyzer-builder.d.ts +6 -3
  48. package/project/flowr-analyzer-builder.js +12 -5
  49. package/project/plugins/file-plugins/files/flowr-rmarkdown-file.d.ts +4 -3
  50. package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +17 -4
  51. package/project/plugins/flowr-analyzer-plugin.d.ts +1 -1
  52. package/project/plugins/flowr-analyzer-plugin.js +1 -1
  53. package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
  54. package/queries/catalog/call-context-query/call-context-query-format.d.ts +1 -1
  55. package/queries/catalog/call-context-query/call-context-query-format.js +1 -2
  56. package/queries/catalog/dependencies-query/function-info/read-functions.js +6 -0
  57. package/queries/catalog/dependencies-query/function-info/write-functions.js +7 -0
  58. package/queries/catalog/input-sources-query/input-source-functions.d.ts +6 -0
  59. package/queries/catalog/input-sources-query/input-source-functions.js +50 -0
  60. package/queries/catalog/input-sources-query/input-sources-query-executor.d.ts +1 -1
  61. package/queries/catalog/input-sources-query/input-sources-query-executor.js +19 -31
  62. package/queries/catalog/input-sources-query/input-sources-query-format.d.ts +2 -1
  63. package/queries/catalog/input-sources-query/input-sources-query-format.js +26 -8
  64. package/queries/catalog/input-sources-query/simple-input-classifier.d.ts +33 -28
  65. package/queries/catalog/input-sources-query/simple-input-classifier.js +192 -99
  66. package/r-bridge/lang-4.x/ast/model/model.d.ts +4 -4
  67. package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +3 -3
  68. package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +3 -3
  69. package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +3 -3
  70. package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +3 -3
  71. package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +3 -3
  72. package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +3 -3
  73. package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +3 -3
  74. package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
  75. package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +3 -3
  76. package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +3 -3
  77. package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +3 -3
  78. package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +3 -3
  79. package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +3 -3
  80. package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -3
  81. package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +3 -3
  82. package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +3 -3
  83. package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +3 -3
  84. package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -3
  85. package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +3 -3
  86. package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +3 -3
  87. package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +3 -3
  88. package/util/record.d.ts +18 -3
  89. package/util/record.js +22 -1
  90. package/util/version.js +1 -1
  91. package/linter/rules/problematic-eval.d.ts +0 -44
  92. package/linter/rules/problematic-eval.js +0 -83
  93. package/project/plugins/flowr-analyzer-plugin-defaults.d.ts +0 -5
  94. package/project/plugins/flowr-analyzer-plugin-defaults.js +0 -37
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.10.3",
3
+ "version": "2.10.5",
4
4
  "description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "repository": {
@@ -167,10 +167,10 @@
167
167
  "devDependencies": {
168
168
  "@commitlint/cli": "^20.5.0",
169
169
  "@commitlint/config-angular": "^20.5.0",
170
- "@eagleoutice/eslint-config-flowr": "^1.0.36",
170
+ "@eagleoutice/eslint-config-flowr": "^1.0.40",
171
171
  "@eslint/eslintrc": "^3.3.3",
172
172
  "@eslint/js": "^9.39.2",
173
- "@j-ulrich/release-it-regex-bumper": "^5.3.0",
173
+ "@j-ulrich/release-it-regex-bumper": "^5.4.0",
174
174
  "@types/command-line-args": "^5.2.3",
175
175
  "@types/command-line-usage": "^5.0.4",
176
176
  "@types/commonmark": "^0.27.10",
@@ -188,7 +188,7 @@
188
188
  "eslint": "^9.39.2",
189
189
  "license-checker-rseidelsohn": "^4.4.2",
190
190
  "npm-run-all": "^4.1.5",
191
- "release-it": "^19.2.3",
191
+ "release-it": "^20.0.0",
192
192
  "ts-node": "^10.9.2",
193
193
  "typedoc": "^0.28.17",
194
194
  "typedoc-plugin-missing-exports": "^4.1.2",
@@ -34,11 +34,12 @@ export declare class FlowrAnalyzerBuilder {
34
34
  private parser?;
35
35
  private input?;
36
36
  private readonly plugins;
37
+ private readonly withDefaultPlugins;
37
38
  /**
38
39
  * Creates a new builder for the {@link FlowrAnalyzer}.
39
- * By default, the standard set of plugins as returned by {@link FlowrAnalyzerPluginDefaults} are registered.
40
+ * By default, the standard set of plugins as returned by {@link FlowrConfig#defaultPlugins} are registered.
40
41
  * @param withDefaultPlugins - Whether to register the default plugins upon creation. Default is `true`.
41
- * @see {@link FlowrAnalyzerPluginDefaults} - for the default plugin set.
42
+ * @see {@link FlowrDefaultPlugins} - for the default plugin set.
42
43
  * @see {@link FlowrAnalyzerBuilder#registerPlugins} - to add more plugins.
43
44
  * @see {@link FlowrAnalyzerBuilder#unregisterPlugins} - to remove plugins.
44
45
  */
@@ -53,6 +54,8 @@ export declare class FlowrAnalyzerBuilder {
53
54
  amendConfig(func: (config: DeepWritable<FlowrConfig>) => FlowrConfig | void): this;
54
55
  /**
55
56
  * Overwrite the configuration used by the resulting analyzer.
57
+ * This also unloads all default plugins and reloads them as set in the new config
58
+ * if the withDefaultPlugins flag was set in the constructor
56
59
  * @param config - The new configuration.
57
60
  */
58
61
  setConfig(config: FlowrConfig): this;
@@ -78,7 +81,7 @@ export declare class FlowrAnalyzerBuilder {
78
81
  setInput(input: Omit<NormalizeRequiredInput, 'context'>): this;
79
82
  /**
80
83
  * Register one or multiple additional plugins.
81
- * For the default plugin set, please refer to {@link FlowrAnalyzerPluginDefaults}, they can be registered
84
+ * For the default plugin set, please refer to {@link FlowrDefaultPlugins}, they can be registered
82
85
  * by passing `true` to the {@link FlowrAnalyzerBuilder} constructor.
83
86
  * @param plugin - One or multiple plugins to register.
84
87
  * @see {@link FlowrAnalyzerBuilder#unregisterPlugins} to remove plugins.
@@ -7,7 +7,6 @@ const engines_1 = require("../engines");
7
7
  const assert_1 = require("../util/assert");
8
8
  const flowr_analyzer_context_1 = require("./context/flowr-analyzer-context");
9
9
  const flowr_analyzer_cache_1 = require("./cache/flowr-analyzer-cache");
10
- const flowr_analyzer_plugin_defaults_1 = require("./plugins/flowr-analyzer-plugin-defaults");
11
10
  const plugin_registry_1 = require("./plugins/plugin-registry");
12
11
  /**
13
12
  * Builder for the {@link FlowrAnalyzer}, use it to configure all analysis aspects before creating the analyzer instance
@@ -37,17 +36,19 @@ class FlowrAnalyzerBuilder {
37
36
  parser;
38
37
  input;
39
38
  plugins = new Map();
39
+ withDefaultPlugins;
40
40
  /**
41
41
  * Creates a new builder for the {@link FlowrAnalyzer}.
42
- * By default, the standard set of plugins as returned by {@link FlowrAnalyzerPluginDefaults} are registered.
42
+ * By default, the standard set of plugins as returned by {@link FlowrConfig#defaultPlugins} are registered.
43
43
  * @param withDefaultPlugins - Whether to register the default plugins upon creation. Default is `true`.
44
- * @see {@link FlowrAnalyzerPluginDefaults} - for the default plugin set.
44
+ * @see {@link FlowrDefaultPlugins} - for the default plugin set.
45
45
  * @see {@link FlowrAnalyzerBuilder#registerPlugins} - to add more plugins.
46
46
  * @see {@link FlowrAnalyzerBuilder#unregisterPlugins} - to remove plugins.
47
47
  */
48
48
  constructor(withDefaultPlugins = true) {
49
+ this.withDefaultPlugins = withDefaultPlugins;
49
50
  if (withDefaultPlugins) {
50
- this.registerPlugins(...(0, flowr_analyzer_plugin_defaults_1.FlowrAnalyzerPluginDefaults)());
51
+ this.registerPlugins(...this.flowrConfig.defaultPlugins);
51
52
  }
52
53
  }
53
54
  /**
@@ -64,9 +65,15 @@ class FlowrAnalyzerBuilder {
64
65
  }
65
66
  /**
66
67
  * Overwrite the configuration used by the resulting analyzer.
68
+ * This also unloads all default plugins and reloads them as set in the new config
69
+ * if the withDefaultPlugins flag was set in the constructor
67
70
  * @param config - The new configuration.
68
71
  */
69
72
  setConfig(config) {
73
+ if (this.withDefaultPlugins) {
74
+ this.unregisterPlugins(...this.flowrConfig.defaultPlugins.map(p => Array.isArray(p) ? p[0] : p));
75
+ this.registerPlugins(...config.defaultPlugins);
76
+ }
70
77
  this.flowrConfig = config;
71
78
  return this;
72
79
  }
@@ -104,7 +111,7 @@ class FlowrAnalyzerBuilder {
104
111
  }
105
112
  /**
106
113
  * Register one or multiple additional plugins.
107
- * For the default plugin set, please refer to {@link FlowrAnalyzerPluginDefaults}, they can be registered
114
+ * For the default plugin set, please refer to {@link FlowrDefaultPlugins}, they can be registered
108
115
  * by passing `true` to the {@link FlowrAnalyzerBuilder} constructor.
109
116
  * @param plugin - One or multiple plugins to register.
110
117
  * @see {@link FlowrAnalyzerBuilder#unregisterPlugins} to remove plugins.
@@ -3,7 +3,7 @@ import { FlowrFile } from '../../../context/flowr-file';
3
3
  import { type Node } from 'commonmark';
4
4
  /**
5
5
  * This decorates a text file and parses its contents as a R Markdown file.
6
- * Finnaly, it provides access to the single cells, and all cells fused together as one R file.
6
+ * Finally, it provides access to the single cells, and all cells fused together as one R file.
7
7
  */
8
8
  export declare class FlowrRMarkdownFile extends FlowrFile<string> {
9
9
  private data?;
@@ -24,8 +24,9 @@ export declare class FlowrRMarkdownFile extends FlowrFile<string> {
24
24
  protected loadContent(): string;
25
25
  static from(file: FlowrFileProvider<string> | FlowrRMarkdownFile): FlowrRMarkdownFile;
26
26
  }
27
+ export type CodeBlockOptions = Map<string, string>;
27
28
  export interface CodeBlock {
28
- options: string;
29
+ options: CodeBlockOptions;
29
30
  code: string;
30
31
  }
31
32
  export type CodeBlockEx = CodeBlock & {
@@ -59,4 +60,4 @@ export declare function restoreBlocksWithoutMd(blocks: CodeBlockEx[], totalLines
59
60
  /**
60
61
  * Parses the options of an R code block from its header and content
61
62
  */
62
- export declare function parseCodeBlockOptions(header: string, content: string): string;
63
+ export declare function parseCodeBlockOptions(header: string, content: string): CodeBlockOptions;
@@ -15,7 +15,7 @@ const gray_matter_1 = __importDefault(require("gray-matter"));
15
15
  const log_1 = require("../../../../util/log");
16
16
  /**
17
17
  * This decorates a text file and parses its contents as a R Markdown file.
18
- * Finnaly, it provides access to the single cells, and all cells fused together as one R file.
18
+ * Finally, it provides access to the single cells, and all cells fused together as one R file.
19
19
  */
20
20
  class FlowrRMarkdownFile extends flowr_file_1.FlowrFile {
21
21
  data;
@@ -78,9 +78,14 @@ function parseRMarkdownFile(raw) {
78
78
  if (!isRCodeBlock(node)) {
79
79
  continue;
80
80
  }
81
+ const options = parseCodeBlockOptions(node.info, node.literal);
82
+ const engineOpt = options.get('engine');
83
+ if (engineOpt !== undefined && engineOpt.trim().toLowerCase() !== 'r') {
84
+ continue;
85
+ }
81
86
  blocks.push({
82
87
  code: node.literal,
83
- options: parseCodeBlockOptions(node.info, node.literal),
88
+ options: options,
84
89
  startpos: { line: node.sourcepos[0][0] + 1, col: 0 }
85
90
  });
86
91
  }
@@ -91,6 +96,7 @@ function parseRMarkdownFile(raw) {
91
96
  options: frontmatter?.data ?? {}
92
97
  };
93
98
  }
99
+ // We need the [\s,] part, otherwise {rust} would also match
94
100
  const RTagRegex = /{[rR](?:[\s,][^}]*)?}/;
95
101
  /**
96
102
  * Checks whether a CommonMark node is an R code block
@@ -123,6 +129,7 @@ function restoreBlocksWithoutMd(blocks, totalLines) {
123
129
  goToLine(totalLines + 1);
124
130
  return output;
125
131
  }
132
+ const OptionsRegex = /([\w_.-]*)\s*[:=]\s*["']?([^,"']*)/g;
126
133
  /**
127
134
  * Parses the options of an R code block from its header and content
128
135
  */
@@ -135,9 +142,15 @@ function parseCodeBlockOptions(header, content) {
135
142
  if (!line.trim().startsWith('#|')) {
136
143
  break;
137
144
  }
138
- const opt = line.substring(3);
145
+ const opt = line.substring(2).trim();
139
146
  opts += opts.length === 0 ? opt : `, ${opt}`;
140
147
  }
141
- return opts;
148
+ const parsedOptions = new Map();
149
+ for (const match of opts.matchAll(OptionsRegex)) {
150
+ if (match[1] && match[2] !== undefined) { // key must not be empty, but value can be empty string for example
151
+ parsedOptions.set(match[1], match[2]);
152
+ }
153
+ }
154
+ return parsedOptions;
142
155
  }
143
156
  //# sourceMappingURL=flowr-rmarkdown-file.js.map
@@ -73,7 +73,7 @@ export interface FlowrAnalyzerPluginInterface<In = unknown, Out = In> {
73
73
  * For example, if you want to create a plugin that determines the loading order of files, extend {@link FlowrAnalyzerLoadingOrderPlugin} instead.
74
74
  * These classes also provide sensible overrides of {@link FlowrAnalyzerPlugin.defaultPlugin} to be used when no plugin of this type is registered or triggered.
75
75
  *
76
- * For a collection of default plugins, see {@link FlowrAnalyzerPluginDefaults}.
76
+ * For a collection of default plugins, see {@link FlowrDefaultPlugins}.
77
77
  */
78
78
  export declare abstract class FlowrAnalyzerPlugin<In = unknown, Out extends AsyncOrSync<unknown> = In> implements FlowrAnalyzerPluginInterface<In, Out> {
79
79
  abstract readonly name: string;
@@ -53,7 +53,7 @@ const generalPluginLog = log_1.log.getSubLogger({ name: 'plugins' });
53
53
  * For example, if you want to create a plugin that determines the loading order of files, extend {@link FlowrAnalyzerLoadingOrderPlugin} instead.
54
54
  * These classes also provide sensible overrides of {@link FlowrAnalyzerPlugin.defaultPlugin} to be used when no plugin of this type is registered or triggered.
55
55
  *
56
- * For a collection of default plugins, see {@link FlowrAnalyzerPluginDefaults}.
56
+ * For a collection of default plugins, see {@link FlowrDefaultPlugins}.
57
57
  */
58
58
  class FlowrAnalyzerPlugin {
59
59
  /**
@@ -77,14 +77,14 @@ function promoteQueryCallNames(queries) {
77
77
  ...q.fileFilter,
78
78
  filter: promoteCallName(q.fileFilter.filter)
79
79
  },
80
- linkTo: Array.isArray(q.linkTo) ? q.linkTo.map(l => ({
80
+ linkTo: q.linkTo ? Array.isArray(q.linkTo) ? q.linkTo.map(l => ({
81
81
  ...l,
82
82
  callName: promoteCallName(l.callName)
83
83
  })) : {
84
84
  ...q.linkTo,
85
85
  /* we have to add another promotion layer whenever we add something without this call name */
86
86
  callName: promoteCallName(q.linkTo.callName)
87
- }
87
+ } : undefined
88
88
  };
89
89
  }
90
90
  else {
@@ -88,7 +88,7 @@ export type LinkTo<CallName extends CallNameTypes = CallNameTypes, AttachLinkInf
88
88
  attachLinkInfo?: AttachLinkInfo;
89
89
  };
90
90
  export interface SubCallContextQueryFormat<CallName extends CallNameTypes = CallNameTypes, AttachLinkInfo = NoInfo> extends DefaultCallContextQueryFormat<CallName> {
91
- readonly linkTo: LinkTo<CallName, AttachLinkInfo> | LinkTo<CallName, AttachLinkInfo>[];
91
+ readonly linkTo?: LinkTo<CallName, AttachLinkInfo> | LinkTo<CallName, AttachLinkInfo>[];
92
92
  }
93
93
  export interface CallContextQuerySubKindResult {
94
94
  /** The id of the call vertex identified within the supplied dataflow graph */
@@ -29,8 +29,7 @@ exports.CallContextQueryDefinition = {
29
29
  executor: call_context_query_executor_1.executeCallContextQueries,
30
30
  asciiSummarizer: async (formatter, analyzer, queryResults, result) => {
31
31
  const out = queryResults;
32
- result.push(`Query: ${(0, ansi_1.bold)('call-context', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
33
- result.push((0, query_print_1.asciiCallContext)(formatter, out, (await analyzer.normalize()).idMap));
32
+ result.push(`Query: ${(0, ansi_1.bold)('call-context', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`, (0, query_print_1.asciiCallContext)(formatter, out, (await analyzer.normalize()).idMap));
34
33
  return true;
35
34
  },
36
35
  schema: joi_1.default.object({
@@ -108,5 +108,11 @@ exports.ReadFunctions = [
108
108
  { package: 'rpolars', name: 'pl_scan_ipc', argIdx: 0, argName: 'source', resolveValue: true, ignoreIf: 'arg-missing' },
109
109
  { package: 'rpolars', name: 'pl_scan_ndjson', argIdx: 0, argName: 'source', resolveValue: true, ignoreIf: 'arg-missing' },
110
110
  { package: 'rpolars', name: 'pl_scan_parquet', argIdx: 0, argName: 'source', resolveValue: true, ignoreIf: 'arg-missing' },
111
+ { package: 'rio', name: 'import', argIdx: 0, argName: 'file', resolveValue: true },
112
+ { package: 'rio', name: 'import_list', argIdx: 0, argName: 'file', resolveValue: true },
113
+ { package: 'openxlsx', name: 'read.xlsx', argIdx: 0, argName: 'file', resolveValue: true },
114
+ { package: 'openxlsx', name: 'loadWorkbook', argIdx: 0, argName: 'file', resolveValue: true },
115
+ { package: 'readODS', name: 'read_ods', argIdx: 0, argName: 'path', resolveValue: true },
116
+ { package: 'vroom', name: 'vroom', argIdx: 0, argName: 'file', resolveValue: true },
111
117
  ];
112
118
  //# sourceMappingURL=read-functions.js.map
@@ -115,6 +115,13 @@ exports.WriteFunctions = [
115
115
  { package: 'rpolars', name: 'write_csv', argIdx: 0, argName: 'file', resolveValue: true, ignoreIf: 'arg-missing' },
116
116
  { package: 'rpolars', name: 'write_ndjson', argIdx: 0, argName: 'file', resolveValue: true, ignoreIf: 'arg-missing' },
117
117
  { package: 'rpolars', name: 'write_parquet', argIdx: 0, argName: 'file', resolveValue: true, ignoreIf: 'arg-missing' },
118
+ { package: 'data.table', name: 'fwrite', argIdx: 1, argName: 'file', resolveValue: true },
119
+ { package: 'writexl', name: 'write_xlsx', argIdx: 1, argName: 'path', resolveValue: true },
120
+ { package: 'openxlsx', name: 'write.xlsx', argIdx: 1, argName: 'file', resolveValue: true },
121
+ { package: 'vroom', name: 'vroom_write', argIdx: 1, argName: 'file', resolveValue: true },
122
+ { package: 'vroom', name: 'vroom_write_lines', argIdx: 1, argName: 'file', resolveValue: true },
123
+ { package: 'rio', name: 'export', argIdx: 1, argName: 'file', resolveValue: true },
124
+ { package: 'rio', name: 'export_list', argIdx: 1, argName: 'file', resolveValue: true },
118
125
  { package: 'magick', name: 'image_write', argIdx: 1, argName: 'path', resolveValue: true, ignoreIf: 'arg-missing' },
119
126
  ];
120
127
  //# sourceMappingURL=write-functions.js.map
@@ -0,0 +1,6 @@
1
+ import type { Identifier } from '../../../dataflow/environments/identifier';
2
+ export declare const PureFunctions: Identifier[];
3
+ export declare const SystemFunctions: Identifier[];
4
+ export declare const FfiFunctions: Identifier[];
5
+ export declare const LangFunctions: Identifier[];
6
+ export declare const OptionsFunctions: Identifier[];
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OptionsFunctions = exports.LangFunctions = exports.FfiFunctions = exports.SystemFunctions = exports.PureFunctions = void 0;
4
+ exports.PureFunctions = [
5
+ 'paste', 'paste0', 'parse', '+', '-', '*',
6
+ '/', '^', '%%', '%/%', '&', '|', '!', '&&', '||',
7
+ '<', '>', '<=', '>=', '==', '!=', ':',
8
+ 'abs', 'sign', 'sqrt', 'exp', 'log', 'log10', 'log2',
9
+ 'sin', 'cos', 'tan', 'asin', 'acos', 'atan',
10
+ 'length', 'nchar', 'dim', 'nrow', 'ncol',
11
+ 'c', 'list', 'data.frame',
12
+ 'ifelse', 'switch', 'factor', 'as.factor',
13
+ 'round', 'floor', 'ceiling', 'trunc',
14
+ 'substr', 'substring', 'strsplit',
15
+ 'min', 'max', 'range', 'sum', 'prod', 'mean', 'median', 'var', 'sd',
16
+ 'head', 'tail', 'seq', 'rep',
17
+ 'apply', 'lapply', 'sapply', 'vapply', 'tapply',
18
+ 'matrix', 'array',
19
+ 'rownames', 'colnames',
20
+ 'list.files', 'tolower', 'toupper', 'printf',
21
+ '<-', '->', '=', '<<-', '->>', 'assign', 'get',
22
+ '[', '[[', '$', 'length<-', 'dim<-', 'names<-', 'colnames<-', 'rownames<-',
23
+ 'as.character', 'as.numeric', 'as.logical', 'as.raw', 'as.list', 'as.data.frame', 'as.matrix', 'as.array',
24
+ 'identity', 'invisible', 'return', 'force', 'missing',
25
+ 'print', 'cat', 'message', 'warning', 'stop',
26
+ 'format', 'sprintf', 'formatC',
27
+ 'is.na', 'is.null', 'is.numeric', 'is.character',
28
+ 'which', 'match', 'order', 'sort', 'unique', 'duplicated', 'na.omit',
29
+ 'grep', 'grepl', 'sub', 'gsub', 'regexpr', 'gregexpr', 'regexec', 'regmatches',
30
+ 'as.integer', 'as.double', 'as.complex',
31
+ 'trimws', 'seq_len', 'seq_along', 'rep.int',
32
+ 'pmin', 'pmax', 'cumsum', 'cumprod', 'cummax', 'cummin', 'diff', 'signif',
33
+ 'table', 'prop.table', 'xtabs',
34
+ 'rbind', 'cbind', 't', 'crossprod', 'tcrossprod',
35
+ 'colSums', 'rowSums', 'colMeans', 'rowMeans',
36
+ 'solve', 'det', 'eigen',
37
+ 'is.factor', 'is.logical', 'is.vector', 'is.matrix', 'is.data.frame',
38
+ ];
39
+ exports.SystemFunctions = ['system', 'system2', 'pipe', 'shell', 'shell.exec'];
40
+ exports.FfiFunctions = ['.C', '.Call', '.Fortran', '.External', 'dyn.load', 'sourceCpp', 'getNativeSymbolInfo'];
41
+ exports.LangFunctions = [
42
+ 'substitute', 'quote', 'enquote', 'bquote',
43
+ 'call', 'as.call', 'expression', 'as.expression', // 'str2lang', 'str2expression',
44
+ 'as.name', 'as.symbol', 'alist', 'as.language', 'evalq',
45
+ 'expr', 'exprs', 'enexpr', 'enexprs', 'inject',
46
+ 'quo', 'quos', 'enquo', 'enquos', 'enquo0', 'enquos0',
47
+ 'sym', 'syms', 'ensym', 'ensyms'
48
+ ];
49
+ exports.OptionsFunctions = ['options', 'getOption', 'Sys.getenv'];
50
+ //# sourceMappingURL=input-source-functions.js.map
@@ -1,5 +1,5 @@
1
1
  import type { BasicQueryData } from '../../base-query-format';
2
- import type { InputSourcesQuery, InputSourcesQueryResult } from './input-sources-query-format';
2
+ import { type InputSourcesQuery, type InputSourcesQueryResult } from './input-sources-query-format';
3
3
  /**
4
4
  * Execute an input sources query
5
5
  */
@@ -1,15 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.executeInputSourcesQuery = executeInputSourcesQuery;
4
+ const input_sources_query_format_1 = require("./input-sources-query-format");
4
5
  const log_1 = require("../../../util/log");
5
6
  const parse_1 = require("../../../slicing/criterion/parse");
6
7
  const r_function_definition_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-function-definition");
7
8
  const model_1 = require("../../../r-bridge/lang-4.x/ast/model/model");
8
9
  const df_helper_1 = require("../../../dataflow/graph/df-helper");
9
10
  const simple_input_classifier_1 = require("./simple-input-classifier");
10
- const network_functions_1 = require("../../../linter/rules/network-functions");
11
- const seeded_randomness_1 = require("../../../linter/rules/seeded-randomness");
12
- const read_functions_1 = require("../dependencies-query/function-info/read-functions");
11
+ const flowr_search_executor_1 = require("../../../search/flowr-search-executor");
12
+ const record_1 = require("../../../util/record");
13
13
  /**
14
14
  * Execute an input sources query
15
15
  */
@@ -18,6 +18,7 @@ async function executeInputSourcesQuery({ analyzer }, queries) {
18
18
  const results = {};
19
19
  const nast = await analyzer.normalize();
20
20
  const df = await analyzer.dataflow();
21
+ const defaultConfig = await resolveSearches(analyzer, input_sources_query_format_1.DefaultInputClassifierConfig);
21
22
  for (const query of queries) {
22
23
  const key = query.criterion;
23
24
  if (results[key]) {
@@ -27,34 +28,8 @@ async function executeInputSourcesQuery({ analyzer }, queries) {
27
28
  const provenanceNode = nast.idMap.get(criterionId);
28
29
  const fdef = r_function_definition_1.RFunctionDefinition.rootFunctionDefinition(provenanceNode, nast.idMap);
29
30
  const provenance = df_helper_1.Dataflow.provenanceGraph(criterionId, df.graph, fdef ? model_1.RNode.collectAllIds(fdef) : undefined);
30
- results[key] = (0, simple_input_classifier_1.classifyInput)(criterionId, provenance, {
31
- networkFns: query.config?.networkFns ?? network_functions_1.NETWORK_FUNCTIONS.info.defaultConfig.fns,
32
- randomFns: query.config?.randomFns ?? seeded_randomness_1.SEEDED_RANDOMNESS.info.defaultConfig.randomnessConsumers,
33
- pureFns: query.config?.pureFns ?? ['paste', 'paste0', 'parse', '+', '-', '*',
34
- '/', '^', '%%', '%/%', '&', '|', '!', '&&', '||',
35
- '<', '>', '<=', '>=', '==', '!=', ':',
36
- 'abs', 'sign', 'sqrt', 'exp', 'log', 'log10', 'log2',
37
- 'sin', 'cos', 'tan', 'asin', 'acos', 'atan',
38
- 'length', 'nchar', 'dim', 'nrow', 'ncol',
39
- 'c', 'list', 'data.frame',
40
- 'ifelse', 'switch', 'factor', 'as.factor',
41
- 'round', 'floor', 'ceiling', 'trunc',
42
- 'substr', 'substring', 'strsplit',
43
- 'min', 'max', 'range', 'sum', 'prod', 'mean', 'median', 'var', 'sd',
44
- 'head', 'tail', 'seq', 'rep',
45
- 'apply', 'lapply', 'sapply', 'vapply', 'tapply',
46
- 'matrix', 'array', 'substitute', 'quote', 'bquote', 'enquote', 'enexpr', 'enexprs', 'enquo', 'enquos',
47
- 'expression', 'call', 'as.call', 'as.expression',
48
- 'rownames', 'colnames',
49
- 'list.files', 'tolower', 'toupper', 'printf',
50
- '<-', '->', '=', '<<-', '->>', 'assign', 'get',
51
- '[', '[[', '$', 'length<-', 'dim<-', 'names<-', 'colnames<-', 'rownames<-',
52
- 'as.character', 'as.numeric', 'as.logical', 'as.list', 'as.data.frame', 'as.matrix', 'as.array',
53
- 'identity', 'invisible', 'return', 'force', 'missing',
54
- 'print', 'cat', 'message', 'warning', 'stop'
55
- ],
56
- readFileFns: query.config?.readFileFns ?? read_functions_1.ReadFunctions.map(f => f.name)
57
- });
31
+ const config = { ...defaultConfig, ...(await resolveSearches(analyzer, query?.config ?? {})) };
32
+ results[key] = (0, simple_input_classifier_1.classifyInput)(criterionId, provenance, config, df.graph);
58
33
  }
59
34
  return {
60
35
  '.meta': {
@@ -63,4 +38,17 @@ async function executeInputSourcesQuery({ analyzer }, queries) {
63
38
  results
64
39
  };
65
40
  }
41
+ async function resolveSearches(analyzer, config) {
42
+ const result = {};
43
+ for (const [key, value] of record_1.Record.entries(config)) {
44
+ if (value === undefined || Array.isArray(value)) {
45
+ result[key] = value;
46
+ }
47
+ else {
48
+ const searchResult = await (0, flowr_search_executor_1.runSearch)(value, analyzer);
49
+ result[key] = searchResult.getElements().map(element => element.node.info.id);
50
+ }
51
+ }
52
+ return result;
53
+ }
66
54
  //# sourceMappingURL=input-sources-query-executor.js.map
@@ -3,7 +3,7 @@ import type { SlicingCriterion } from '../../../slicing/criterion/parse';
3
3
  import type { ParsedQueryLine } from '../../query';
4
4
  import Joi from 'joi';
5
5
  import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
6
- import type { InputClassifierConfig, InputSources } from './simple-input-classifier';
6
+ import { type InputClassifierConfig, type InputSources } from './simple-input-classifier';
7
7
  import type { ReplOutput } from '../../../cli/repl/commands/repl-main';
8
8
  import type { FlowrConfig } from '../../../config';
9
9
  import { executeInputSourcesQuery } from './input-sources-query-executor';
@@ -21,6 +21,7 @@ export interface InputSourcesQuery extends BaseQueryFormat {
21
21
  readonly criterion: SlicingCriterion;
22
22
  readonly config?: InputSourcesQueryConfig;
23
23
  }
24
+ export declare const DefaultInputClassifierConfig: InputClassifierConfig;
24
25
  export interface InputSourcesQueryResult extends BaseQueryResult {
25
26
  /** For each query key, a list of classified input sources (each with id and all traces) */
26
27
  results: Record<string, InputSources>;
@@ -3,13 +3,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.InputSourcesDefinition = void 0;
6
+ exports.InputSourcesDefinition = exports.DefaultInputClassifierConfig = void 0;
7
7
  const ansi_1 = require("../../../util/text/ansi");
8
8
  const time_1 = require("../../../util/text/time");
9
9
  const joi_1 = __importDefault(require("joi"));
10
+ const simple_input_classifier_1 = require("./simple-input-classifier");
10
11
  const slice_query_parser_1 = require("../../../cli/repl/parser/slice-query-parser");
11
12
  const input_sources_query_executor_1 = require("./input-sources-query-executor");
12
13
  const range_1 = require("../../../util/range");
14
+ const flowr_search_builder_1 = require("../../../search/flowr-search-builder");
15
+ const read_functions_1 = require("../dependencies-query/function-info/read-functions");
16
+ const input_source_functions_1 = require("./input-source-functions");
17
+ exports.DefaultInputClassifierConfig = {
18
+ [simple_input_classifier_1.InputTraceType.Pure]: input_source_functions_1.PureFunctions,
19
+ [simple_input_classifier_1.InputType.File]: read_functions_1.ReadFunctions.map(readFunction => readFunction.name),
20
+ [simple_input_classifier_1.InputType.Network]: flowr_search_builder_1.Q.fromQuery({ type: 'linter', rules: ['network-functions'] }),
21
+ [simple_input_classifier_1.InputType.Random]: flowr_search_builder_1.Q.fromQuery({ type: 'linter', rules: ['seeded-randomness'] }),
22
+ [simple_input_classifier_1.InputType.System]: input_source_functions_1.SystemFunctions,
23
+ [simple_input_classifier_1.InputType.Ffi]: input_source_functions_1.FfiFunctions,
24
+ [simple_input_classifier_1.InputType.Lang]: input_source_functions_1.LangFunctions,
25
+ [simple_input_classifier_1.InputType.Options]: input_source_functions_1.OptionsFunctions
26
+ };
13
27
  function inputSourcesQueryLineParser(output, line, _config) {
14
28
  const criterion = (0, slice_query_parser_1.sliceCriteriaParser)(line[0]);
15
29
  if (!criterion || criterion.length !== 1) {
@@ -29,10 +43,11 @@ exports.InputSourcesDefinition = {
29
43
  const nast = (await analyzer.normalize()).idMap;
30
44
  for (const [key, sources] of Object.entries(out.results)) {
31
45
  result.push(` ╰ Input Sources for ${key}`);
32
- for (const { id, trace, type } of sources) {
46
+ for (const { id, trace, types, value } of sources) {
33
47
  const kNode = nast.get(id);
34
48
  const kLoc = kNode ? range_1.SourceLocation.format(range_1.SourceLocation.fromNode(kNode)) : 'unknown location';
35
- result.push(` ╰ ${kLoc} (id: ${id}), type: ${JSON.stringify(type)}, trace: ${trace}`);
49
+ const valueStr = value !== undefined ? `, value: ${JSON.stringify(value)}` : '';
50
+ result.push(` ╰ ${kLoc} (id: ${id}), type: ${JSON.stringify(types)}, trace: ${trace}${valueStr}`);
36
51
  }
37
52
  }
38
53
  return true;
@@ -42,11 +57,14 @@ exports.InputSourcesDefinition = {
42
57
  type: joi_1.default.string().valid('input-sources').required().description('The type of the query.'),
43
58
  criterion: joi_1.default.string().required().description('The slicing criterion to use.'),
44
59
  config: joi_1.default.object({
45
- networkFunctions: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that fetch data from the network.'),
46
- randomnessConsumers: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that consume randomness.'),
47
- randomnessProducers: joi_1.default.array().items(joi_1.default.object({ type: joi_1.default.string().valid('function', 'assignment'), name: joi_1.default.string().required() })).optional().description('Functions or assignments that produce randomness seeds.'),
48
- configurableFunctions: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that read configuration (options/env).'),
49
- pureFunctions: joi_1.default.array().items(joi_1.default.string()).optional().description('Deterministic functions that keep constant inputs constant.'),
60
+ [simple_input_classifier_1.InputTraceType.Pure]: joi_1.default.array().items(joi_1.default.string()).optional().description('Deterministic/pure functions: functions that preserve constantness of their inputs (e.g., arithmetic, parse).'),
61
+ [simple_input_classifier_1.InputType.File]: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that read from the filesystem and produce data (e.g., read.csv, readRDS).'),
62
+ [simple_input_classifier_1.InputType.Network]: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that fetch data from the network (e.g., download.file, url connections).'),
63
+ [simple_input_classifier_1.InputType.Random]: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that produce randomness (e.g., runif, rnorm).'),
64
+ [simple_input_classifier_1.InputType.System]: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that execute system commands (e.g., system, system2, shell, pipe).'),
65
+ [simple_input_classifier_1.InputType.Ffi]: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that call native code via the R FFI (.C, .Call, .Fortran, .External, dyn.load).'),
66
+ [simple_input_classifier_1.InputType.Lang]: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that produce language objects (e.g., substitute, quote, bquote, expression).'),
67
+ [simple_input_classifier_1.InputType.Options]: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that access or set global options (e.g., options, getOption).'),
50
68
  }).optional()
51
69
  }).description('Input Sources query definition'),
52
70
  flattenInvolvedNodes: (queryResults) => {