@eagleoutice/flowr 2.1.10 → 2.1.12

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 (74) hide show
  1. package/README.md +1 -0
  2. package/cli/flowr.js +8 -0
  3. package/cli/repl/commands/repl-query.js +14 -3
  4. package/cli/repl/server/connection.js +1 -1
  5. package/core/steps/pipeline/default-pipelines.d.ts +6 -0
  6. package/core/steps/pipeline/default-pipelines.js +6 -0
  7. package/dataflow/environments/resolve-by-name.d.ts +2 -1
  8. package/dataflow/environments/resolve-by-name.js +2 -1
  9. package/dataflow/graph/vertex.d.ts +4 -0
  10. package/dataflow/graph/vertex.js +3 -1
  11. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +29 -26
  12. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +1 -2
  13. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +28 -24
  14. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +2 -1
  15. package/documentation/doc-util/doc-dfg.js +1 -1
  16. package/documentation/doc-util/doc-query.js +1 -1
  17. package/documentation/doc-util/doc-search.d.ts +25 -0
  18. package/documentation/doc-util/doc-search.js +121 -0
  19. package/documentation/doc-util/doc-types.d.ts +10 -2
  20. package/documentation/doc-util/doc-types.js +81 -3
  21. package/documentation/print-dataflow-graph-wiki.js +1 -1
  22. package/documentation/print-interface-wiki.js +31 -15
  23. package/documentation/print-normalized-ast-wiki.js +4 -4
  24. package/documentation/print-query-wiki.js +35 -0
  25. package/documentation/print-search-wiki.d.ts +1 -0
  26. package/documentation/print-search-wiki.js +74 -0
  27. package/package.json +2 -1
  28. package/queries/base-query-format.d.ts +2 -2
  29. package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
  30. package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
  31. package/queries/catalog/cluster-query/cluster-query-executor.d.ts +1 -1
  32. package/queries/catalog/cluster-query/cluster-query-executor.js +1 -1
  33. package/queries/catalog/config-query/config-query-executor.d.ts +3 -0
  34. package/queries/catalog/config-query/config-query-executor.js +18 -0
  35. package/queries/catalog/config-query/config-query-format.d.ts +16 -0
  36. package/queries/catalog/config-query/config-query-format.js +24 -0
  37. package/queries/catalog/dataflow-query/dataflow-query-executor.d.ts +1 -1
  38. package/queries/catalog/dataflow-query/dataflow-query-executor.js +1 -1
  39. package/queries/catalog/dependencies-query/dependencies-query-executor.js +2 -2
  40. package/queries/catalog/lineage-query/lineage-query-executor.d.ts +1 -1
  41. package/queries/catalog/lineage-query/lineage-query-executor.js +1 -1
  42. package/queries/catalog/location-map-query/location-map-query-format.js +1 -1
  43. package/queries/catalog/search-query/search-query-executor.d.ts +3 -0
  44. package/queries/catalog/search-query/search-query-executor.js +27 -0
  45. package/queries/catalog/search-query/search-query-format.d.ts +72 -0
  46. package/queries/catalog/search-query/search-query-format.js +29 -0
  47. package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
  48. package/queries/catalog/static-slice-query/static-slice-query-executor.js +1 -1
  49. package/queries/query.d.ts +65 -1
  50. package/queries/query.js +5 -1
  51. package/r-bridge/lang-4.x/ast/model/type.d.ts +4 -0
  52. package/r-bridge/lang-4.x/ast/model/type.js +3 -1
  53. package/search/flowr-search-builder.d.ts +193 -0
  54. package/search/flowr-search-builder.js +192 -0
  55. package/search/flowr-search-executor.d.ts +9 -0
  56. package/search/flowr-search-executor.js +16 -0
  57. package/search/flowr-search-filters.d.ts +74 -0
  58. package/search/flowr-search-filters.js +136 -0
  59. package/search/flowr-search-printer.d.ts +10 -0
  60. package/search/flowr-search-printer.js +85 -0
  61. package/search/flowr-search-traverse.d.ts +7 -0
  62. package/search/flowr-search-traverse.js +12 -0
  63. package/search/flowr-search.d.ts +58 -0
  64. package/search/flowr-search.js +29 -0
  65. package/search/search-executor/search-generators.d.ts +37 -0
  66. package/search/search-executor/search-generators.js +64 -0
  67. package/search/search-executor/search-transformer.d.ts +57 -0
  68. package/search/search-executor/search-transformer.js +99 -0
  69. package/search/search-optimizer/search-optimizer.d.ts +9 -0
  70. package/search/search-optimizer/search-optimizer.js +89 -0
  71. package/util/arrays.d.ts +13 -0
  72. package/util/assert.d.ts +1 -1
  73. package/util/mermaid/mermaid.js +17 -0
  74. package/util/version.js +1 -1
@@ -10,6 +10,8 @@ exports.getTypePathLink = getTypePathLink;
10
10
  exports.getTypesFromFolderAsMermaid = getTypesFromFolderAsMermaid;
11
11
  exports.implSnippet = implSnippet;
12
12
  exports.printHierarchy = printHierarchy;
13
+ exports.shortLink = shortLink;
14
+ exports.getDocumentationForType = getDocumentationForType;
13
15
  const typescript_1 = __importDefault(require("typescript"));
14
16
  const assert_1 = require("../../util/assert");
15
17
  const doc_files_1 = require("./doc-files");
@@ -18,6 +20,7 @@ const path_1 = __importDefault(require("path"));
18
20
  const mermaid_1 = require("../../util/mermaid/mermaid");
19
21
  const doc_code_1 = require("./doc-code");
20
22
  const doc_structure_1 = require("./doc-structure");
23
+ const html_hover_over_1 = require("../../util/html-hover-over");
21
24
  function getSourceFiles(fileNames) {
22
25
  try {
23
26
  const program = typescript_1.default.createProgram(fileNames, { target: typescript_1.default.ScriptTarget.ESNext });
@@ -171,6 +174,42 @@ function collectHierarchyInformation(sourceFiles, options) {
171
174
  }),
172
175
  });
173
176
  }
177
+ else if (typescript_1.default.isVariableDeclaration(node) || typescript_1.default.isExportDeclaration(node) || typescript_1.default.isExportAssignment(node) || typescript_1.default.isDeclarationStatement(node)) {
178
+ const name = node.name?.getText(sourceFile) ?? '';
179
+ const comments = getTextualComments(node);
180
+ hierarchyList.push({
181
+ name: dropGenericsFromType(name),
182
+ node,
183
+ kind: 'variable',
184
+ extends: [],
185
+ comments,
186
+ generics: [],
187
+ filePath: sourceFile.fileName,
188
+ lineNumber: getStartLine(node, sourceFile),
189
+ });
190
+ }
191
+ else if (typescript_1.default.isPropertyAssignment(node) || typescript_1.default.isPropertyDeclaration(node) || typescript_1.default.isPropertySignature(node)
192
+ || typescript_1.default.isMethodDeclaration(node) || typescript_1.default.isMethodSignature(node) || typescript_1.default.isFunctionDeclaration(node)) {
193
+ const name = node.name?.getText(sourceFile) ?? '';
194
+ // get the name of the object/enclosing type
195
+ let parent = node.parent;
196
+ while (typeof parent === 'object' && parent !== undefined && !('name' in parent)) {
197
+ parent = parent.parent;
198
+ }
199
+ if (typeof parent === 'object' && 'name' in parent) {
200
+ const comments = getTextualComments(node);
201
+ hierarchyList.push({
202
+ name: dropGenericsFromType(name),
203
+ node,
204
+ kind: 'variable',
205
+ extends: [parent.name?.getText(sourceFile) ?? ''],
206
+ comments,
207
+ generics: [],
208
+ filePath: sourceFile.fileName,
209
+ lineNumber: getStartLine(node, sourceFile),
210
+ });
211
+ }
212
+ }
174
213
  typescript_1.default.forEachChild(node, child => visit(child, sourceFile));
175
214
  };
176
215
  sourceFiles.forEach(sourceFile => {
@@ -266,7 +305,7 @@ function getTypesFromFolderAsMermaid(options) {
266
305
  }
267
306
  return getTypesFromFileAsMermaid(files, options);
268
307
  }
269
- function implSnippet(node, program, nesting = 0) {
308
+ function implSnippet(node, program, showName = true, nesting = 0) {
270
309
  (0, assert_1.guard)(node !== undefined, 'Node must be defined => invalid change of type name?');
271
310
  const indent = ' '.repeat(nesting * 2);
272
311
  const bold = node.kind === 'interface' || node.kind === 'enum' ? '**' : '';
@@ -274,7 +313,8 @@ function implSnippet(node, program, nesting = 0) {
274
313
  let text = node.comments?.join('\n') ?? '';
275
314
  const code = node.node.getFullText(program.getSourceFile(node.node.getSourceFile().fileName));
276
315
  text += `\n<details><summary style="color:gray">Defined at <a href="${getTypePathLink(node)}">${getTypePathLink(node, '.')}</a></summary>\n\n${(0, doc_code_1.codeBlock)('ts', code)}\n\n</details>\n`;
277
- return `${indent} * ${bold}[${node.name}](${getTypePathLink(node)})${bold} ${sep}${indent} ${text.replaceAll('\t', ' ').split(/\n/g).join(`\n${indent} `)}`;
316
+ const init = showName ? ` * ${bold}[${node.name}](${getTypePathLink(node)})${bold} ${sep}${indent}` : '';
317
+ return ` ${indent} ${showName ? init : ''} ${text.replaceAll('\t', ' ').split(/\n/g).join(`\n${indent} `)}`;
278
318
  }
279
319
  exports.mermaidHide = ['Leaf', 'Location', 'Namespace', 'Base', 'WithChildren', 'Partial', 'RAccessBase'];
280
320
  function printHierarchy({ program, hierarchy, root, collapseFromNesting = 1, initialNesting = 0, maxDepth = 20 }) {
@@ -285,7 +325,7 @@ function printHierarchy({ program, hierarchy, root, collapseFromNesting = 1, ini
285
325
  if (!node) {
286
326
  return '';
287
327
  }
288
- const thisLine = implSnippet(node, program, initialNesting);
328
+ const thisLine = implSnippet(node, program, true, initialNesting);
289
329
  const result = [];
290
330
  for (const baseType of node.extends) {
291
331
  if (exports.mermaidHide.includes(baseType)) {
@@ -302,4 +342,42 @@ function printHierarchy({ program, hierarchy, root, collapseFromNesting = 1, ini
302
342
  return thisLine + (out ? '\n' + out : '');
303
343
  }
304
344
  }
345
+ function retrieveNode(name, hierarchy) {
346
+ let container = undefined;
347
+ if (name.includes('::')) {
348
+ [container, name] = name.split('::');
349
+ }
350
+ const node = hierarchy.find(e => e.name === name);
351
+ if (!node) {
352
+ return undefined;
353
+ }
354
+ else if (container && !node.extends.includes(container)) {
355
+ return undefined;
356
+ }
357
+ return [container, name, node];
358
+ }
359
+ /**
360
+ * Create a short link to a type in the documentation
361
+ * @param name - The name of the type, e.g. `MyType`, may include a container, e.g. `MyContainer::MyType` (this works with function nestings too)
362
+ * @param hierarchy - The hierarchy of types to search in
363
+ * @param codeStyle - Whether to use code style for the link
364
+ */
365
+ function shortLink(name, hierarchy, codeStyle = true) {
366
+ const res = retrieveNode(name, hierarchy);
367
+ if (!res) {
368
+ return '';
369
+ }
370
+ const [pkg, mainName, node] = res;
371
+ const comments = node.comments?.join('\n').replace(/\\?\n|```[a-zA-Z]*|\s\s*/g, ' ').replace(/<\/?code>|/g, '') ?? '';
372
+ return `[${codeStyle ? '<code>' : ''}${(node.comments?.length ?? 0) > 0 ?
373
+ (0, html_hover_over_1.textWithTooltip)(pkg ? `${pkg}::<b>${mainName}</b>` : mainName, (0, mermaid_1.escapeMarkdown)(comments.length > 400 ? comments.slice(0, 400) + '...' : comments)) : node.name}${codeStyle ? '</code>' : ''}](${getTypePathLink(node)})`;
374
+ }
375
+ function getDocumentationForType(name, hierarchy) {
376
+ const res = retrieveNode(name, hierarchy);
377
+ if (!res) {
378
+ return '';
379
+ }
380
+ const [, , node] = res;
381
+ return node.comments?.join('\n') ?? '';
382
+ }
305
383
  //# sourceMappingURL=doc-types.js.map
@@ -689,7 +689,7 @@ async function getText(shell) {
689
689
  });
690
690
  return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'dataflow graph', rVersion: rversion })}
691
691
 
692
- This page briefly summarizes flowR's dataflow graph, represented by ${graph_1.DataflowGraph.name} in ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/graph.ts')}.
692
+ This page briefly summarizes flowR's dataflow graph, represented by ${(0, doc_types_1.shortLink)('DataflowGraph', vertexType.info)} in ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/graph.ts')}.
693
693
  In case you want to manually build such a graph (e.g., for testing), you can use the builder in ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/dataflowgraph-builder.ts')}.
694
694
  This wiki page focuses on explaining what such a dataflow graph looks like!
695
695
 
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  const shell_1 = require("../r-bridge/shell");
4
7
  const log_1 = require("../../test/functionality/_helper/log");
@@ -19,6 +22,8 @@ const flowr_main_options_1 = require("../cli/flowr-main-options");
19
22
  const doc_issue_1 = require("./doc-util/doc-issue");
20
23
  const pipeline_executor_1 = require("../core/pipeline-executor");
21
24
  const doc_structure_1 = require("./doc-util/doc-structure");
25
+ const doc_types_1 = require("./doc-util/doc-types");
26
+ const path_1 = __importDefault(require("path"));
22
27
  async function explainServer(shell) {
23
28
  (0, doc_data_server_messages_1.documentAllServerMessages)();
24
29
  return `
@@ -162,6 +167,11 @@ function explainConfigFile() {
162
167
  When running _flowR_, you may want to specify some behaviors with a dedicated configuration file.
163
168
  By default, flowR looks for a file named \`${flowr_main_options_1.defaultConfigFile}\` in the current working directory (or any higher directory).
164
169
  You can also specify a different file with ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'config-file')} or pass the configuration inline using ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'config-json')}.
170
+ To inspect the current configuration, you can run flowr with the ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'verbose')} flag, or use the \`config\` [Query](${doc_files_1.FlowrWikiBaseRef}/Query%20API).
171
+ Within the REPL this works by running the following:
172
+
173
+ ${(0, doc_code_1.codeBlock)('shell', ':query @config')}
174
+
165
175
 
166
176
  The following summarizes the configuration options:
167
177
 
@@ -209,8 +219,8 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify({
209
219
  - \`loadDefaults\` (boolean, initially \`true\`): If set to \`true\`, the default built-in definitions are loaded before applying the custom definitions. Setting this flag to \`false\` explicitly disables the loading of the default definitions.
210
220
  - \`definitions\` (array, initially empty): Allows to overwrite or define new built-in elements. Each object within must have a \`type\` which is one of the below. Furthermore, they may define a string array of \`names\` which specifies the identifiers to bind the definitions to. You may use \`assumePrimitive\` to specify whether _flowR_ should assume that this is a primitive non-library definition (so you probably just do not want to specify the key).
211
221
 
212
- | Type | Description | Example |
213
- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
222
+ | Type | Description | Example |
223
+ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
214
224
  | \`constant\` | Additionally allows for a \`value\` this should resolve to. | \`{ type: 'constant', names: ['NULL', 'NA'], value: null }\` |
215
225
  | \`function\` | Is a rather flexible way to define and bind built-in functions. For the time, we do not have extensive documentation to cover all the cases, so please either consult the sources with the \`default-builtin-config.ts\` or open a [new issue](${doc_issue_1.NewIssueUrl}). | \`{ type: 'function', names: ['next'], processor: 'builtin:default', config: { cfg: ExitPointType.Next } }\` |
216
226
  | \`replacement\` | A comfortable way to specify replacement functions like \`$<-\` or \`names<-\`. \`suffixes\` describes the... suffixes to attach automatically. | \`{ type: 'replacement', suffixes: ['<-', '<<-'], names: ['[', '[['] }\` |
@@ -229,37 +239,43 @@ ${(0, schema_1.describeSchema)(config_1.flowrConfigFileSchema, ansi_1.markdownFo
229
239
  `;
230
240
  }
231
241
  function explainWritingCode(shell) {
242
+ const types = (0, doc_types_1.getTypesFromFolderAsMermaid)({
243
+ rootFolder: path_1.default.resolve('./src/r-bridge/'),
244
+ files: [path_1.default.resolve('./src/core/pipeline-executor.ts'), path_1.default.resolve('./src/core/steps/pipeline/default-pipelines.ts')],
245
+ typeName: 'RShell',
246
+ inlineTypes: doc_types_1.mermaidHide
247
+ });
232
248
  return `
233
249
 
234
250
 
235
251
  _flowR_ can be used as a [module](${doc_files_1.FlowrNpmRef}) and offers several main classes and interfaces that are interesting for extension writers
236
252
  (see the [Visual Studio Code extension](${doc_files_1.FlowrGithubBaseRef}/vscode-flowr) or the [core](${doc_files_1.FlowrWikiBaseRef}/Core) wiki page for more information).
237
253
 
238
- ### Using the \`${shell_1.RShell.name}\` to Interact with R
254
+ ### Using the ${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info)} to Interact with R
239
255
 
240
- The \`${shell_1.RShell.name}\` class allows to interface with the \`R\`&nbsp;ecosystem installed on the host system.
256
+ The ${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info)} class allows interfacing with the \`R\`&nbsp;ecosystem installed on the host system.
241
257
  For now, there are no (real) alternatives, although we plan on providing more flexible drop-in replacements.
242
258
 
243
259
  > [!IMPORTANT]
244
- > Each \`${shell_1.RShell.name}\` controls a new instance of the R&nbsp;interpreter, make sure to call \`${shell_1.RShell.name}::${shell.close.name}()\` when you’re done.
260
+ > Each ${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info)} controls a new instance of the R&nbsp;interpreter, make sure to call <code>${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info, false)}::${shell.close.name}()</code> when you’re done.
245
261
 
246
- You can start a new "session" simply by constructing a new object with \`new ${shell_1.RShell.name}()\`.
262
+ You can start a new "session" simply by constructing a new object with <code>new ${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info, false)}()</code>.
247
263
 
248
- However, there are several options which may be of interest (e.g., to automatically revive the shell in case of errors or to control the name location of the R process on the system).
264
+ However, there are several options that may be of interest (e.g., to automatically revive the shell in case of errors or to control the name location of the R process on the system).
249
265
 
250
- With a shell object (let's call it \`shell\`), you can execute R code by using \`${shell_1.RShell.name}::${shell.sendCommand.name}\`,
266
+ With a shell object (let's call it \`shell\`), you can execute R code by using <code>${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info, false)}::${shell.sendCommand.name}</code>,
251
267
  for example \`shell.${shell.sendCommand.name}("1 + 1")\`.
252
- However, this does not return anything, so if you want to collect the output of your command, use \`${shell_1.RShell.name}::${shell.sendCommandWithOutput.name}\` instead.
268
+ However, this does not return anything, so if you want to collect the output of your command, use <code>${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info, false)}::${shell.sendCommandWithOutput.name}</code> instead.
253
269
 
254
- Besides that, the command \`${shell_1.RShell.name}::${shell.tryToInjectHomeLibPath.name}\` may be of interest, as it enables all libraries available on the host system.
270
+ Besides that, the command <code>${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info, false)}::${shell.tryToInjectHomeLibPath.name}</code> may be of interest, as it enables all libraries available on the host system.
255
271
 
256
272
  ### The Pipeline Executor
257
273
 
258
274
  Once, in the beginning, _flowR_ was meant to produce a dataflow graph merely to provide *program slices*.
259
- However, with continuous updates, the [dataflow graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow&20Graph) repeatedly proves to be the more interesting part.
275
+ However, with continuous updates, the [dataflow graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph) repeatedly proves to be the more interesting part.
260
276
  With this, we restructured _flowR_'s originally *hardcoded* pipeline to be far more flexible.
261
277
  Now, it can be theoretically extended or replaced with arbitrary steps, optional steps, and what we call 'decorations' of these steps.
262
- In short, if you still "just want to slice" you can do it like this:
278
+ In short, if you still "just want to slice" you can do it like this with the ${(0, doc_types_1.shortLink)(pipeline_executor_1.PipelineExecutor.name, types.info)}:
263
279
 
264
280
  ${(0, doc_code_1.codeBlock)('ts', `
265
281
  const slicer = new ${pipeline_executor_1.PipelineExecutor.name}(DEFAULT_SLICING_PIPELINE, {
@@ -276,9 +292,9 @@ const slice = await slicer.allRemainingSteps()
276
292
  <summary style='color:gray'>More Information</summary>
277
293
 
278
294
  If you compare this, with what you would have done with the old (and removed) \`SteppingSlicer\`,
279
- this essentially just requires you to replace the \`SteppingSlicer\` with the \`${pipeline_executor_1.PipelineExecutor.name}\`
280
- and to pass the \`DEFAULT_SLICING_PIPELINE\` as the first argument.
281
- The \`${pipeline_executor_1.PipelineExecutor.name}\`...
295
+ this essentially just requires you to replace the \`SteppingSlicer\` with the ${(0, doc_types_1.shortLink)(pipeline_executor_1.PipelineExecutor.name, types.info)}
296
+ and to pass the ${(0, doc_types_1.shortLink)('DEFAULT_SLICING_PIPELINE', types.info)} as the first argument.
297
+ The ${(0, doc_types_1.shortLink)(pipeline_executor_1.PipelineExecutor.name, types.info)}...
282
298
 
283
299
  1. allows investigating the results of all intermediate steps
284
300
  2. Can be executed step-by-step
@@ -24,7 +24,7 @@ async function getText(shell) {
24
24
  const now = performance.now();
25
25
  const types = (0, doc_types_1.getTypesFromFolderAsMermaid)({
26
26
  rootFolder: path_1.default.resolve('./src/r-bridge/lang-4.x/ast/model/'),
27
- files: [path_1.default.resolve('./src/abstract-interpretation/normalized-ast-fold.ts')],
27
+ files: [path_1.default.resolve('./src/abstract-interpretation/normalized-ast-fold.ts'), path_1.default.resolve('./src/core/steps/pipeline/default-pipelines.ts')],
28
28
  typeName: 'RNode',
29
29
  inlineTypes: doc_types_1.mermaidHide
30
30
  });
@@ -77,7 +77,7 @@ ${(0, doc_code_1.codeBlock)('mermaid', types.text)}
77
77
  _The generation of the class diagram required ${(0, time_1.printAsMs)(elapsed)}._
78
78
  </details>
79
79
 
80
- Node types are controlled by the \`${'RType'}\` enum (see ${(0, doc_files_1.getFilePathMd)('../r-bridge/lang-4.x/ast/model/type.ts')}),
80
+ Node types are controlled by the ${(0, doc_types_1.shortLink)('RType', types.info)} enum (see ${(0, doc_files_1.getFilePathMd)('../r-bridge/lang-4.x/ast/model/type.ts')}),
81
81
  which is used to distinguish between different types of nodes.
82
82
  Additionally, every AST node is generic with respect to the \`Info\` type which allows for arbitrary decorations (e.g., parent inforamtion or dataflow constraints).
83
83
  Most notably, the \`info\` field holds the \`id\` of the node, which is used to reference the node in the [dataflow graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph).
@@ -94,8 +94,8 @@ The following segments intend to give you an overview of how to work with the no
94
94
  ## How Get a Normalized AST
95
95
 
96
96
  As explained alongside the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface#the-pipeline-executor) wiki page, you can use the
97
- \`${pipeline_executor_1.PipelineExecutor.name}\` to get the normalized AST. If you are only interested in the normalization,
98
- a pipeline like the \`DEFAULT_NORMALIZE_PIPELINE\` suffices:
97
+ \`${pipeline_executor_1.PipelineExecutor.name}\` to get the ${(0, doc_types_1.shortLink)('NormalizedAst', types.info)}. If you are only interested in the normalization,
98
+ a pipeline like the ${(0, doc_types_1.shortLink)('DEFAULT_NORMALIZE_PIPELINE', types.info)} suffices:
99
99
 
100
100
  ${(0, doc_code_1.codeBlock)('ts', `
101
101
  async function getAst(code: string): Promise<RNode> {
@@ -25,6 +25,10 @@ const doc_cli_option_1 = require("./doc-util/doc-cli-option");
25
25
  const doc_issue_1 = require("./doc-util/doc-issue");
26
26
  const location_map_query_executor_1 = require("../queries/catalog/location-map-query/location-map-query-executor");
27
27
  const identify_link_to_last_call_relation_1 = require("../queries/catalog/call-context-query/identify-link-to-last-call-relation");
28
+ const config_query_executor_1 = require("../queries/catalog/config-query/config-query-executor");
29
+ const search_query_executor_1 = require("../queries/catalog/search-query/search-query-executor");
30
+ const flowr_search_builder_1 = require("../search/flowr-search-builder");
31
+ const vertex_1 = require("../dataflow/graph/vertex");
28
32
  (0, doc_query_1.registerQueryDocumentation)('call-context', {
29
33
  name: 'Call-Context Query',
30
34
  type: 'active',
@@ -190,6 +194,25 @@ ${await (0, doc_query_1.showQuery)(shell, example_query_code_1.exampleQueryCode,
190
194
  `;
191
195
  }
192
196
  });
197
+ (0, doc_query_1.registerQueryDocumentation)('search', {
198
+ name: 'Search Query',
199
+ type: 'active',
200
+ shortDescription: 'Provides access to flowR\'s search API',
201
+ functionName: search_query_executor_1.executeSearch.name,
202
+ functionFile: '../queries/catalog/search-query/search-query-executor.ts',
203
+ buildExplanation: async (shell) => {
204
+ const exampleCode = 'x + 1';
205
+ return `
206
+ With this query you can use the [Search API](${doc_files_1.FlowrWikiBaseRef}/Search%20API) to conduct searches on the flowR analysis result.
207
+
208
+ Using the example code \`${exampleCode}\`, the following query returns all uses of 'x' in the code:
209
+ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
210
+ type: 'search',
211
+ search: flowr_search_builder_1.Q.var('x').filter(vertex_1.VertexType.Use).build()
212
+ }], { showCode: true, collapseQuery: false })}
213
+ `;
214
+ }
215
+ });
193
216
  (0, doc_query_1.registerQueryDocumentation)('id-map', {
194
217
  name: 'Id-Map Query',
195
218
  type: 'active',
@@ -208,6 +231,18 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
208
231
  `;
209
232
  }
210
233
  });
234
+ (0, doc_query_1.registerQueryDocumentation)('config', {
235
+ name: 'Config Query',
236
+ type: 'active',
237
+ shortDescription: 'Returns the current configuration of flowR.',
238
+ functionName: config_query_executor_1.executeConfigQuery.name,
239
+ functionFile: '../queries/catalog/config-query/config-query-format.ts',
240
+ // eslint-disable-next-line @typescript-eslint/require-await -- no need for async here
241
+ buildExplanation: async () => {
242
+ return `
243
+ This query provides access to the current configuration of the flowR instance. See the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information on what the configuration represents.`;
244
+ }
245
+ });
211
246
  (0, doc_query_1.registerQueryDocumentation)('compound', {
212
247
  name: 'Compound Query',
213
248
  type: 'virtual',
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,74 @@
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 shell_1 = require("../r-bridge/shell");
7
+ const log_1 = require("../../test/functionality/_helper/log");
8
+ const doc_files_1 = require("./doc-util/doc-files");
9
+ const doc_auto_gen_1 = require("./doc-util/doc-auto-gen");
10
+ const doc_search_1 = require("./doc-util/doc-search");
11
+ const flowr_search_builder_1 = require("../search/flowr-search-builder");
12
+ const vertex_1 = require("../dataflow/graph/vertex");
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
+ const types = (0, doc_types_1.getTypesFromFolderAsMermaid)({
18
+ rootFolder: path_1.default.resolve('./src/search/'),
19
+ typeName: 'FlowrSearchGenerator',
20
+ inlineTypes: doc_types_1.mermaidHide
21
+ });
22
+ return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'search API', rVersion: rversion })}
23
+
24
+ This page briefly summarizes flowR's search API which provides a set of functions to search for nodes in the [Dataflow Graph](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph) and the
25
+ [Normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST) of a given R code (the search will always consider both, with respect to your search query).
26
+ Please see the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information on how to access this API.
27
+ Within code, you can execute a search using the ${(0, doc_types_1.shortLink)('runSearch', types.info)} function.
28
+
29
+ For an initial motivation, let's have a look at the following example:
30
+
31
+ ${await (0, doc_search_1.showSearch)(shell, 'x <- x * x', flowr_search_builder_1.Q.var('x'))}
32
+
33
+ This returns all references to the variable \`x\` in the code.
34
+ However, the search API is not limited to simple variable references and can do much more.
35
+
36
+ For example, let's have every definition of \`x\` in the code but the first one:
37
+
38
+ ${await (0, doc_search_1.showSearch)(shell, 'x <- x * x\nprint(x)\nx <- y <- 3\nprint(x)\nx <- 2', flowr_search_builder_1.Q.var('x').filter(vertex_1.VertexType.VariableDefinition).skip(1))}
39
+
40
+ In summary, every search has two parts. It is initialized with a _generator_ (such as \`Q.var('x')\`)
41
+ and can be further refined with _transformers_ or _modifiers_.
42
+ Such queries can be constructed starting from the ${(0, doc_types_1.shortLink)('Q', types.info)} object (backed by ${(0, doc_types_1.shortLink)('FlowrSearchGenerator', types.info)}) and
43
+ are fully serializable so you can use them when communicating with the [Query API](${doc_files_1.FlowrWikiBaseRef}/Query%20API).
44
+
45
+ We offer the following generators:
46
+
47
+ ${Object.keys(flowr_search_builder_1.Q).sort().map(key => `- ${(0, doc_types_1.shortLink)(`FlowrSearchGenerator::${key}`, types.info)}\\\n${(0, doc_types_1.getDocumentationForType)(`FlowrSearchGenerator::${key}`, types.info)}`).join('\n')}
48
+
49
+ Likewise, we have a palette of _transformers_ and _modifiers_:
50
+
51
+ ${
52
+ /* let's iterate over all methods of FlowrSearchBuilder */
53
+ Object.getOwnPropertyNames(Object.getPrototypeOf(new flowr_search_builder_1.FlowrSearchBuilder(undefined)))
54
+ .filter(n => n !== 'constructor').sort().map(key => `- ${(0, doc_types_1.shortLink)(`FlowrSearchBuilder::${key}`, types.info)}\\\n${(0, doc_types_1.getDocumentationForType)(`FlowrSearchBuilder::${key}`, types.info)}`).join('\n')}
55
+
56
+ Every search (and consequently the search pipeline) works with an array of ${(0, doc_types_1.shortLink)('FlowrSearchElement', types.info)} (neatly wrapped in ${(0, doc_types_1.shortLink)('FlowrSearchElements', types.info)}).
57
+ Hence, even operations such as \`.first\` or \`.last\` return an array of elements (albeit with a single or no element).
58
+ The search API does its best to stay typesafe wrt. to the return type and the transformers in use.
59
+ In addition, it offers optimizer passes to optimize the search pipeline before execution.
60
+ They are executed with \`.build\` which may happen automatically, whenever you want to run a search using ${(0, doc_types_1.shortLink)('runSearch', types.info)}.
61
+
62
+ `;
63
+ }
64
+ /** if we run this script, we want a Markdown representation of the capabilities */
65
+ if (require.main === module) {
66
+ (0, log_1.setMinLevelOfAllLogs)(6 /* LogLevel.Fatal */);
67
+ const shell = new shell_1.RShell();
68
+ void getText(shell).then(str => {
69
+ console.log(str);
70
+ }).finally(() => {
71
+ shell.close();
72
+ });
73
+ }
74
+ //# sourceMappingURL=print-search-wiki.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.1.10",
3
+ "version": "2.1.12",
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": {
@@ -28,6 +28,7 @@
28
28
  "wiki:df-graph": "ts-node src/documentation/print-dataflow-graph-wiki.ts",
29
29
  "wiki:normalized-ast": "ts-node src/documentation/print-normalized-ast-wiki.ts",
30
30
  "wiki:query-api": "ts-node src/documentation/print-query-wiki.ts",
31
+ "wiki:search-api": "ts-node src/documentation/print-search-wiki.ts",
31
32
  "wiki:linting-and-testing": "ts-node src/documentation/print-linting-and-testing-wiki.ts",
32
33
  "wiki:interface": "ts-node src/documentation/print-interface-wiki.ts",
33
34
  "build": "tsc --project .",
@@ -1,5 +1,5 @@
1
1
  import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
2
- import type { DataflowGraph } from '../dataflow/graph/graph';
2
+ import type { DataflowInformation } from '../dataflow/info';
3
3
  export interface BaseQueryFormat {
4
4
  /** used to select the query type :) */
5
5
  readonly type: string;
@@ -13,5 +13,5 @@ export interface BaseQueryResult {
13
13
  }
14
14
  export interface BasicQueryData {
15
15
  readonly ast: NormalizedAst;
16
- readonly graph: DataflowGraph;
16
+ readonly dataflow: DataflowInformation;
17
17
  }
@@ -9,4 +9,4 @@ import type { BasicQueryData } from '../../base-query-format';
9
9
  * This happens during the main resolution!
10
10
  * 4. Attach `linkTo` calls to the respective calls.
11
11
  */
12
- export declare function executeCallContextQueries({ graph, ast }: BasicQueryData, queries: readonly CallContextQuery[]): CallContextQueryResult;
12
+ export declare function executeCallContextQueries({ dataflow: { graph }, ast }: BasicQueryData, queries: readonly CallContextQuery[]): CallContextQueryResult;
@@ -158,7 +158,7 @@ function doesFilepathMatch(file, filter) {
158
158
  * This happens during the main resolution!
159
159
  * 4. Attach `linkTo` calls to the respective calls.
160
160
  */
161
- function executeCallContextQueries({ graph, ast }, queries) {
161
+ function executeCallContextQueries({ dataflow: { graph }, ast }, queries) {
162
162
  /* omit performance page load */
163
163
  const now = Date.now();
164
164
  /* the node id and call targets if present */
@@ -1,3 +1,3 @@
1
1
  import type { DataflowClusterQuery, DataflowClusterQueryResult } from './cluster-query-format';
2
2
  import type { BasicQueryData } from '../../base-query-format';
3
- export declare function executeDataflowClusterQuery({ graph }: BasicQueryData, queries: readonly DataflowClusterQuery[]): DataflowClusterQueryResult;
3
+ export declare function executeDataflowClusterQuery({ dataflow: { graph } }: BasicQueryData, queries: readonly DataflowClusterQuery[]): DataflowClusterQueryResult;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.executeDataflowClusterQuery = executeDataflowClusterQuery;
4
4
  const log_1 = require("../../../util/log");
5
5
  const cluster_1 = require("../../../dataflow/cluster");
6
- function executeDataflowClusterQuery({ graph }, queries) {
6
+ function executeDataflowClusterQuery({ dataflow: { graph } }, queries) {
7
7
  if (queries.length !== 1) {
8
8
  log_1.log.warn('The dataflow cluster query expects only up to one query, but got', queries.length);
9
9
  }
@@ -0,0 +1,3 @@
1
+ import type { ConfigQuery, ConfigQueryResult } from './config-query-format';
2
+ import type { BasicQueryData } from '../../base-query-format';
3
+ export declare function executeConfigQuery(_: BasicQueryData, queries: readonly ConfigQuery[]): ConfigQueryResult;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeConfigQuery = executeConfigQuery;
4
+ const log_1 = require("../../../util/log");
5
+ const config_1 = require("../../../config");
6
+ function executeConfigQuery(_, queries) {
7
+ if (queries.length !== 1) {
8
+ log_1.log.warn('Config query expects only up to one query, but got', queries.length);
9
+ }
10
+ return {
11
+ '.meta': {
12
+ /* there is no sense in measuring a get */
13
+ timing: 0
14
+ },
15
+ config: (0, config_1.getConfig)()
16
+ };
17
+ }
18
+ //# sourceMappingURL=config-query-executor.js.map
@@ -0,0 +1,16 @@
1
+ import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
2
+ import { executeConfigQuery } from './config-query-executor';
3
+ import { type OutputFormatter } from '../../../util/ansi';
4
+ import Joi from 'joi';
5
+ import type { FlowrConfigOptions } from '../../../config';
6
+ export interface ConfigQuery extends BaseQueryFormat {
7
+ readonly type: 'config';
8
+ }
9
+ export interface ConfigQueryResult extends BaseQueryResult {
10
+ readonly config: FlowrConfigOptions;
11
+ }
12
+ export declare const ConfigQueryDefinition: {
13
+ readonly executor: typeof executeConfigQuery;
14
+ readonly asciiSummarizer: (formatter: OutputFormatter, _processed: unknown, queryResults: BaseQueryResult, result: string[]) => boolean;
15
+ readonly schema: Joi.ObjectSchema<any>;
16
+ };
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ConfigQueryDefinition = void 0;
7
+ const config_query_executor_1 = require("./config-query-executor");
8
+ const ansi_1 = require("../../../util/ansi");
9
+ const time_1 = require("../../../util/time");
10
+ const joi_1 = __importDefault(require("joi"));
11
+ const json_1 = require("../../../util/json");
12
+ exports.ConfigQueryDefinition = {
13
+ executor: config_query_executor_1.executeConfigQuery,
14
+ asciiSummarizer: (formatter, _processed, queryResults, result) => {
15
+ const out = queryResults;
16
+ result.push(`Query: ${(0, ansi_1.bold)('config', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
17
+ result.push(` ╰ Config:\n${JSON.stringify(out.config, json_1.jsonReplacer, 4)}`);
18
+ return true;
19
+ },
20
+ schema: joi_1.default.object({
21
+ type: joi_1.default.string().valid('config').required().description('The type of the query.'),
22
+ }).description('The config query retrieves the current configuration of the flowR instance.')
23
+ };
24
+ //# sourceMappingURL=config-query-format.js.map
@@ -1,3 +1,3 @@
1
1
  import type { DataflowQuery, DataflowQueryResult } from './dataflow-query-format';
2
2
  import type { BasicQueryData } from '../../base-query-format';
3
- export declare function executeDataflowQuery({ graph }: BasicQueryData, queries: readonly DataflowQuery[]): DataflowQueryResult;
3
+ export declare function executeDataflowQuery({ dataflow: { graph } }: BasicQueryData, queries: readonly DataflowQuery[]): DataflowQueryResult;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.executeDataflowQuery = executeDataflowQuery;
4
4
  const log_1 = require("../../../util/log");
5
- function executeDataflowQuery({ graph }, queries) {
5
+ function executeDataflowQuery({ dataflow: { graph } }, queries) {
6
6
  if (queries.length !== 1) {
7
7
  log_1.log.warn('Dataflow query expects only up to one query, but got', queries.length);
8
8
  }
@@ -83,7 +83,7 @@ function makeCallContextQuery(functions, kind) {
83
83
  }
84
84
  function getResults(data, results, kind, functions, makeInfo, additionalAllowedTypes) {
85
85
  return Object.entries(results?.kinds[kind]?.subkinds ?? {}).flatMap(([name, results]) => results.flatMap(({ id, linkedIds }) => {
86
- const vertex = data.graph.getVertex(id);
86
+ const vertex = data.dataflow.graph.getVertex(id);
87
87
  const info = functions.find(f => f.name === name);
88
88
  let index = info.argIdx;
89
89
  if (info.argName) {
@@ -99,7 +99,7 @@ function getResults(data, results, kind, functions, makeInfo, additionalAllowedT
99
99
  return args.flatMap(a => (0, objects_1.compactRecord)(makeInfo(id, vertex, a, linkedIds)));
100
100
  })).filter(assert_1.isNotUndefined) ?? [];
101
101
  }
102
- function getArgumentValue({ graph }, vertex, argumentIndex, additionalAllowedTypes) {
102
+ function getArgumentValue({ dataflow: { graph } }, vertex, argumentIndex, additionalAllowedTypes) {
103
103
  if (vertex) {
104
104
  if (argumentIndex === 'unnamed') {
105
105
  // return all unnamed arguments
@@ -1,3 +1,3 @@
1
1
  import type { LineageQuery, LineageQueryResult } from './lineage-query-format';
2
2
  import type { BasicQueryData } from '../../base-query-format';
3
- export declare function executeLineageQuery({ graph, ast }: BasicQueryData, queries: readonly LineageQuery[]): LineageQueryResult;
3
+ export declare function executeLineageQuery({ dataflow: { graph }, ast }: BasicQueryData, queries: readonly LineageQuery[]): LineageQueryResult;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.executeLineageQuery = executeLineageQuery;
4
4
  const log_1 = require("../../../util/log");
5
5
  const repl_lineage_1 = require("../../../cli/repl/commands/repl-lineage");
6
- function executeLineageQuery({ graph, ast }, queries) {
6
+ function executeLineageQuery({ dataflow: { graph }, ast }, queries) {
7
7
  const start = Date.now();
8
8
  const result = {};
9
9
  for (const { criterion } of queries) {
@@ -19,6 +19,6 @@ exports.LocationMapQueryDefinition = {
19
19
  },
20
20
  schema: joi_1.default.object({
21
21
  type: joi_1.default.string().valid('location-map').required().description('The type of the query.'),
22
- }).description('The id map query retrieves the location of every id in the ast.')
22
+ }).description('The location map query retrieves the location of every id in the ast.')
23
23
  };
24
24
  //# sourceMappingURL=location-map-query-format.js.map
@@ -0,0 +1,3 @@
1
+ import type { BasicQueryData } from '../../base-query-format';
2
+ import type { SearchQuery, SearchQueryResult } from './search-query-format';
3
+ export declare function executeSearch({ ast, dataflow }: BasicQueryData, queries: readonly SearchQuery[]): SearchQueryResult;