@eagleoutice/flowr 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +41 -29
  2. package/abstract-interpretation/data-frame/absint-visitor.d.ts +2 -3
  3. package/abstract-interpretation/data-frame/absint-visitor.js +14 -16
  4. package/abstract-interpretation/data-frame/mappers/function-mapper.js +3 -3
  5. package/abstract-interpretation/data-frame/semantics.d.ts +1 -1
  6. package/abstract-interpretation/data-frame/semantics.js +7 -10
  7. package/abstract-interpretation/data-frame/shape-inference.js +2 -8
  8. package/benchmark/slicer.js +7 -5
  9. package/benchmark/summarizer/second-phase/graph.js +1 -1
  10. package/benchmark/summarizer/second-phase/process.js +1 -1
  11. package/cli/benchmark-app.d.ts +1 -0
  12. package/cli/benchmark-app.js +1 -0
  13. package/cli/benchmark-helper-app.d.ts +1 -0
  14. package/cli/benchmark-helper-app.js +4 -3
  15. package/cli/common/options.js +2 -0
  16. package/cli/repl/commands/repl-query.js +1 -1
  17. package/cli/repl/server/connection.js +14 -5
  18. package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
  19. package/control-flow/basic-cfg-guided-visitor.js +0 -6
  20. package/control-flow/cfg-simplification.d.ts +6 -0
  21. package/control-flow/cfg-simplification.js +18 -9
  22. package/control-flow/control-flow-graph.d.ts +2 -8
  23. package/control-flow/control-flow-graph.js +1 -6
  24. package/control-flow/extract-cfg.d.ts +2 -2
  25. package/control-flow/extract-cfg.js +52 -63
  26. package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
  27. package/core/steps/all/static-slicing/00-slice.js +9 -3
  28. package/core/steps/pipeline/default-pipelines.d.ts +74 -74
  29. package/dataflow/environments/built-in.d.ts +2 -2
  30. package/dataflow/environments/built-in.js +13 -12
  31. package/dataflow/graph/dataflowgraph-builder.js +2 -2
  32. package/dataflow/graph/graph.js +1 -1
  33. package/dataflow/graph/invert-dfg.d.ts +2 -0
  34. package/dataflow/graph/invert-dfg.js +17 -0
  35. package/documentation/doc-util/doc-query.js +1 -1
  36. package/documentation/doc-util/doc-search.js +2 -2
  37. package/documentation/print-cfg-wiki.js +3 -4
  38. package/documentation/print-core-wiki.js +2 -2
  39. package/documentation/print-dataflow-graph-wiki.js +7 -0
  40. package/documentation/print-faq-wiki.js +4 -0
  41. package/documentation/print-linter-wiki.js +32 -4
  42. package/documentation/print-linting-and-testing-wiki.js +13 -1
  43. package/documentation/print-onboarding-wiki.js +4 -0
  44. package/documentation/print-query-wiki.js +12 -3
  45. package/linter/linter-executor.js +1 -2
  46. package/linter/linter-format.d.ts +26 -4
  47. package/linter/linter-format.js +25 -6
  48. package/linter/linter-rules.d.ts +40 -12
  49. package/linter/linter-rules.js +3 -1
  50. package/linter/rules/absolute-path.d.ts +4 -7
  51. package/linter/rules/absolute-path.js +9 -6
  52. package/linter/rules/dataframe-access-validation.d.ts +3 -1
  53. package/linter/rules/dataframe-access-validation.js +3 -1
  54. package/linter/rules/dead-code.d.ts +43 -0
  55. package/linter/rules/dead-code.js +50 -0
  56. package/linter/rules/deprecated-functions.d.ts +3 -2
  57. package/linter/rules/deprecated-functions.js +3 -1
  58. package/linter/rules/file-path-validity.d.ts +4 -4
  59. package/linter/rules/file-path-validity.js +8 -6
  60. package/linter/rules/naming-convention.d.ts +4 -3
  61. package/linter/rules/naming-convention.js +3 -1
  62. package/linter/rules/seeded-randomness.d.ts +4 -3
  63. package/linter/rules/seeded-randomness.js +3 -1
  64. package/linter/rules/unused-definition.d.ts +2 -0
  65. package/linter/rules/unused-definition.js +3 -1
  66. package/package.json +1 -1
  67. package/queries/catalog/dependencies-query/dependencies-query-executor.js +6 -1
  68. package/queries/catalog/dependencies-query/function-info/read-functions.js +1 -0
  69. package/queries/catalog/dependencies-query/function-info/write-functions.js +1 -0
  70. package/queries/catalog/linter-query/linter-query-format.js +1 -1
  71. package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
  72. package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
  73. package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
  74. package/queries/catalog/search-query/search-query-executor.js +1 -1
  75. package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -1
  76. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
  77. package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
  78. package/queries/query-print.d.ts +1 -1
  79. package/queries/query-print.js +0 -1
  80. package/queries/query.d.ts +16 -5
  81. package/queries/query.js +24 -11
  82. package/search/flowr-search-builder.d.ts +6 -6
  83. package/search/flowr-search-executor.d.ts +2 -2
  84. package/search/flowr-search-executor.js +1 -1
  85. package/search/flowr-search.d.ts +13 -8
  86. package/search/flowr-search.js +21 -0
  87. package/search/search-executor/search-enrichers.d.ts +87 -20
  88. package/search/search-executor/search-enrichers.js +44 -5
  89. package/search/search-executor/search-generators.d.ts +4 -4
  90. package/search/search-executor/search-generators.js +12 -7
  91. package/search/search-executor/search-mappers.js +3 -2
  92. package/search/search-executor/search-transformer.d.ts +3 -3
  93. package/search/search-executor/search-transformer.js +2 -2
  94. package/slicing/static/static-slicer.d.ts +4 -2
  95. package/slicing/static/static-slicer.js +10 -4
  96. package/util/collections/arrays.d.ts +2 -0
  97. package/util/collections/arrays.js +9 -0
  98. package/util/mermaid/dfg.js +4 -2
  99. package/util/range.d.ts +1 -0
  100. package/util/range.js +5 -1
  101. package/util/version.js +1 -1
@@ -8,6 +8,20 @@ import type { RShell } from '../../../r-bridge/shell';
8
8
  import type { TreeSitterExecutor } from '../../../r-bridge/lang-4.x/tree-sitter/tree-sitter-executor';
9
9
  import type { FlowrConfigOptions } from '../../../config';
10
10
  export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
11
+ readonly name: "slice";
12
+ readonly humanReadableName: "static slice";
13
+ readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
14
+ readonly processor: (results: {
15
+ dataflow?: import("../../../dataflow/info").DataflowInformation;
16
+ normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
17
+ }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
18
+ readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
19
+ readonly printer: {
20
+ readonly 0: typeof import("../../print/print").internalPrinter;
21
+ };
22
+ readonly dependencies: readonly ["dataflow"];
23
+ readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
24
+ } | {
11
25
  readonly name: "parse";
12
26
  readonly humanReadableName: "parse with R shell";
13
27
  readonly description: "Parse the given R code into an AST";
@@ -60,20 +74,6 @@ export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
60
74
  readonly 4: typeof import("../../print/dataflow-printer").dataflowGraphToMermaidUrl;
61
75
  };
62
76
  readonly dependencies: readonly ["normalize"];
63
- } | {
64
- readonly name: "slice";
65
- readonly humanReadableName: "static slice";
66
- readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
67
- readonly processor: (results: {
68
- dataflow?: import("../../../dataflow/info").DataflowInformation;
69
- normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
70
- }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
71
- readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
72
- readonly printer: {
73
- readonly 0: typeof import("../../print/print").internalPrinter;
74
- };
75
- readonly dependencies: readonly ["dataflow"];
76
- readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
77
77
  } | {
78
78
  readonly name: "reconstruct";
79
79
  readonly humanReadableName: "static code reconstruction";
@@ -90,6 +90,20 @@ export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
90
90
  readonly requiredInput: import("../all/static-slicing/10-reconstruct").ReconstructRequiredInput;
91
91
  }>;
92
92
  export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline").Pipeline<{
93
+ readonly name: "slice";
94
+ readonly humanReadableName: "static slice";
95
+ readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
96
+ readonly processor: (results: {
97
+ dataflow?: import("../../../dataflow/info").DataflowInformation;
98
+ normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
99
+ }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
100
+ readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
101
+ readonly printer: {
102
+ readonly 0: typeof import("../../print/print").internalPrinter;
103
+ };
104
+ readonly dependencies: readonly ["dataflow"];
105
+ readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
106
+ } | {
93
107
  readonly name: "parse";
94
108
  readonly humanReadableName: "parse with R shell";
95
109
  readonly description: "Parse the given R code into an AST";
@@ -142,20 +156,6 @@ export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline"
142
156
  readonly 4: typeof import("../../print/dataflow-printer").dataflowGraphToMermaidUrl;
143
157
  };
144
158
  readonly dependencies: readonly ["normalize"];
145
- } | {
146
- readonly name: "slice";
147
- readonly humanReadableName: "static slice";
148
- readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
149
- readonly processor: (results: {
150
- dataflow?: import("../../../dataflow/info").DataflowInformation;
151
- normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
152
- }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
153
- readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
154
- readonly printer: {
155
- readonly 0: typeof import("../../print/print").internalPrinter;
156
- };
157
- readonly dependencies: readonly ["dataflow"];
158
- readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
159
159
  } | {
160
160
  readonly name: "reconstruct";
161
161
  readonly humanReadableName: "static code reconstruction";
@@ -172,6 +172,20 @@ export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline"
172
172
  readonly requiredInput: import("../all/static-slicing/10-reconstruct").ReconstructRequiredInput;
173
173
  }>;
174
174
  export declare const DEFAULT_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./pipeline").Pipeline<{
175
+ readonly name: "slice";
176
+ readonly humanReadableName: "static slice";
177
+ readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
178
+ readonly processor: (results: {
179
+ dataflow?: import("../../../dataflow/info").DataflowInformation;
180
+ normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
181
+ }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
182
+ readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
183
+ readonly printer: {
184
+ readonly 0: typeof import("../../print/print").internalPrinter;
185
+ };
186
+ readonly dependencies: readonly ["dataflow"];
187
+ readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
188
+ } | {
175
189
  readonly name: "parse";
176
190
  readonly humanReadableName: "parse with R shell";
177
191
  readonly description: "Parse the given R code into an AST";
@@ -224,22 +238,22 @@ export declare const DEFAULT_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./pipel
224
238
  readonly 4: typeof import("../../print/dataflow-printer").dataflowGraphToMermaidUrl;
225
239
  };
226
240
  readonly dependencies: readonly ["normalize"];
227
- } | {
241
+ }>;
242
+ export declare const TREE_SITTER_SLICING_PIPELINE: import("./pipeline").Pipeline<{
228
243
  readonly name: "slice";
229
244
  readonly humanReadableName: "static slice";
230
245
  readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
231
246
  readonly processor: (results: {
232
247
  dataflow?: import("../../../dataflow/info").DataflowInformation;
233
248
  normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
234
- }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
249
+ }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
235
250
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
236
251
  readonly printer: {
237
252
  readonly 0: typeof import("../../print/print").internalPrinter;
238
253
  };
239
254
  readonly dependencies: readonly ["dataflow"];
240
255
  readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
241
- }>;
242
- export declare const TREE_SITTER_SLICING_PIPELINE: import("./pipeline").Pipeline<{
256
+ } | {
243
257
  readonly humanReadableName: "dataflow";
244
258
  readonly processor: (results: {
245
259
  normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
@@ -259,20 +273,6 @@ export declare const TREE_SITTER_SLICING_PIPELINE: import("./pipeline").Pipeline
259
273
  readonly 4: typeof import("../../print/dataflow-printer").dataflowGraphToMermaidUrl;
260
274
  };
261
275
  readonly dependencies: readonly ["normalize"];
262
- } | {
263
- readonly name: "slice";
264
- readonly humanReadableName: "static slice";
265
- readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
266
- readonly processor: (results: {
267
- dataflow?: import("../../../dataflow/info").DataflowInformation;
268
- normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
269
- }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
270
- readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
271
- readonly printer: {
272
- readonly 0: typeof import("../../print/print").internalPrinter;
273
- };
274
- readonly dependencies: readonly ["dataflow"];
275
- readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
276
276
  } | {
277
277
  readonly name: "reconstruct";
278
278
  readonly humanReadableName: "static code reconstruction";
@@ -321,6 +321,20 @@ export declare const TREE_SITTER_SLICING_PIPELINE: import("./pipeline").Pipeline
321
321
  readonly requiredInput: import("../all/core/10-normalize").NormalizeRequiredInput;
322
322
  }>;
323
323
  export declare const TREE_SITTER_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline").Pipeline<{
324
+ readonly name: "slice";
325
+ readonly humanReadableName: "static slice";
326
+ readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
327
+ readonly processor: (results: {
328
+ dataflow?: import("../../../dataflow/info").DataflowInformation;
329
+ normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
330
+ }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
331
+ readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
332
+ readonly printer: {
333
+ readonly 0: typeof import("../../print/print").internalPrinter;
334
+ };
335
+ readonly dependencies: readonly ["dataflow"];
336
+ readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
337
+ } | {
324
338
  readonly humanReadableName: "dataflow";
325
339
  readonly processor: (results: {
326
340
  normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
@@ -340,20 +354,6 @@ export declare const TREE_SITTER_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipel
340
354
  readonly 4: typeof import("../../print/dataflow-printer").dataflowGraphToMermaidUrl;
341
355
  };
342
356
  readonly dependencies: readonly ["normalize"];
343
- } | {
344
- readonly name: "slice";
345
- readonly humanReadableName: "static slice";
346
- readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
347
- readonly processor: (results: {
348
- dataflow?: import("../../../dataflow/info").DataflowInformation;
349
- normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
350
- }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
351
- readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
352
- readonly printer: {
353
- readonly 0: typeof import("../../print/print").internalPrinter;
354
- };
355
- readonly dependencies: readonly ["dataflow"];
356
- readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
357
357
  } | {
358
358
  readonly name: "reconstruct";
359
359
  readonly humanReadableName: "static code reconstruction";
@@ -402,6 +402,20 @@ export declare const TREE_SITTER_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipel
402
402
  readonly requiredInput: import("../all/core/10-normalize").NormalizeRequiredInput;
403
403
  }>;
404
404
  export declare const TREE_SITTER_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./pipeline").Pipeline<{
405
+ readonly name: "slice";
406
+ readonly humanReadableName: "static slice";
407
+ readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
408
+ readonly processor: (results: {
409
+ dataflow?: import("../../../dataflow/info").DataflowInformation;
410
+ normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
411
+ }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
412
+ readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
413
+ readonly printer: {
414
+ readonly 0: typeof import("../../print/print").internalPrinter;
415
+ };
416
+ readonly dependencies: readonly ["dataflow"];
417
+ readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
418
+ } | {
405
419
  readonly humanReadableName: "dataflow";
406
420
  readonly processor: (results: {
407
421
  normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
@@ -421,20 +435,6 @@ export declare const TREE_SITTER_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./p
421
435
  readonly 4: typeof import("../../print/dataflow-printer").dataflowGraphToMermaidUrl;
422
436
  };
423
437
  readonly dependencies: readonly ["normalize"];
424
- } | {
425
- readonly name: "slice";
426
- readonly humanReadableName: "static slice";
427
- readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
428
- readonly processor: (results: {
429
- dataflow?: import("../../../dataflow/info").DataflowInformation;
430
- normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
431
- }, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
432
- readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
433
- readonly printer: {
434
- readonly 0: typeof import("../../print/print").internalPrinter;
435
- };
436
- readonly dependencies: readonly ["dataflow"];
437
- readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
438
438
  } | {
439
439
  readonly name: "parse";
440
440
  readonly humanReadableName: "parse with tree-sitter";
@@ -54,7 +54,7 @@ export interface DefaultBuiltInProcessorConfiguration extends ForceArguments {
54
54
  readonly returnsNthArgument?: number | 'last';
55
55
  readonly cfg?: ExitPointType;
56
56
  readonly readAllArguments?: boolean;
57
- readonly hasUnknownSideEffects?: boolean | LinkTo<RegExp | string>;
57
+ readonly hasUnknownSideEffects?: boolean | LinkTo;
58
58
  /** record mapping the actual function name called to the arguments that should be treated as function calls */
59
59
  readonly treatAsFnCall?: Record<string, readonly string[]>;
60
60
  /** Name that should be used for the origin (useful when needing to differentiate between
@@ -63,7 +63,7 @@ export interface DefaultBuiltInProcessorConfiguration extends ForceArguments {
63
63
  readonly useAsProcessor?: UseAsProcessors;
64
64
  }
65
65
  export type BuiltInEvalHandler = (resolve: VariableResolve, a: RNodeWithParent, env?: REnvironmentInformation, graph?: DataflowGraph, map?: AstIdMap) => Value;
66
- declare function defaultBuiltInProcessor<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: DefaultBuiltInProcessorConfiguration): DataflowInformation;
66
+ declare function defaultBuiltInProcessor<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, { returnsNthArgument, useAsProcessor, forceArgs, readAllArguments, cfg, hasUnknownSideEffects, treatAsFnCall }: DefaultBuiltInProcessorConfiguration): DataflowInformation;
67
67
  export declare function registerBuiltInFunctions<Config extends object, Proc extends BuiltInIdentifierProcessorWithConfig<Config>>(both: boolean, names: readonly Identifier[], processor: Proc, config: Config): void;
68
68
  export declare const BuiltInProcessorMapper: {
69
69
  readonly 'builtin:default': typeof defaultBuiltInProcessor;
@@ -41,30 +41,31 @@ function builtInId(name) {
41
41
  function isBuiltIn(name) {
42
42
  return String(name).startsWith('built-in:');
43
43
  }
44
- function defaultBuiltInProcessor(name, args, rootId, data, config) {
45
- const { information: res, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: config.forceArgs, origin: config.useAsProcessor ?? 'builtin:default' });
46
- if (config.returnsNthArgument !== undefined) {
47
- const arg = config.returnsNthArgument === 'last' ? processedArguments[args.length - 1] : processedArguments[config.returnsNthArgument];
44
+ function defaultBuiltInProcessor(name, args, rootId, data, { returnsNthArgument, useAsProcessor, forceArgs, readAllArguments, cfg, hasUnknownSideEffects, treatAsFnCall }) {
45
+ const activeProcessor = useAsProcessor ?? 'builtin:default';
46
+ const { information: res, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs, origin: activeProcessor });
47
+ if (returnsNthArgument !== undefined) {
48
+ const arg = returnsNthArgument === 'last' ? processedArguments[args.length - 1] : processedArguments[returnsNthArgument];
48
49
  if (arg !== undefined) {
49
50
  res.graph.addEdge(rootId, arg.entryPoint, edge_1.EdgeType.Returns);
50
51
  }
51
52
  }
52
- if (config.readAllArguments) {
53
+ if (readAllArguments) {
53
54
  for (const arg of processedArguments) {
54
55
  if (arg) {
55
56
  res.graph.addEdge(rootId, arg.entryPoint, edge_1.EdgeType.Reads);
56
57
  }
57
58
  }
58
59
  }
59
- if (config.hasUnknownSideEffects) {
60
- if (typeof config.hasUnknownSideEffects !== 'boolean') {
61
- (0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId, config.hasUnknownSideEffects);
60
+ if (hasUnknownSideEffects) {
61
+ if (typeof hasUnknownSideEffects !== 'boolean') {
62
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId, hasUnknownSideEffects);
62
63
  }
63
64
  else {
64
65
  (0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId);
65
66
  }
66
67
  }
67
- const fnCallNames = config.treatAsFnCall?.[name.content];
68
+ const fnCallNames = treatAsFnCall?.[name.content];
68
69
  if (fnCallNames) {
69
70
  for (const arg of args) {
70
71
  if (arg !== r_function_call_1.EmptyArgument && arg.value && fnCallNames.includes(arg.name?.content)) {
@@ -90,13 +91,13 @@ function defaultBuiltInProcessor(name, args, rootId, data, config) {
90
91
  environment: data.environment,
91
92
  onlyBuiltin: false,
92
93
  cds: data.controlDependencies,
93
- origin: [config.useAsProcessor ?? 'builtin:default']
94
+ origin: [activeProcessor]
94
95
  });
95
96
  }
96
97
  }
97
98
  }
98
- if (config.cfg !== undefined) {
99
- res.exitPoints = [...res.exitPoints, { type: config.cfg, nodeId: rootId, controlDependencies: data.controlDependencies }];
99
+ if (cfg !== undefined) {
100
+ res.exitPoints.push({ type: cfg, nodeId: rootId, controlDependencies: data.controlDependencies });
100
101
  }
101
102
  return res;
102
103
  }
@@ -180,7 +180,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
180
180
  fromId = from.nodeId;
181
181
  }
182
182
  else {
183
- const result = (0, flowr_search_executor_1.runSearch)(from.query, data);
183
+ const result = (0, flowr_search_executor_1.runSearch)(from.query, data).getElements();
184
184
  (0, assert_1.guard)(result.length === 1, `from query result should yield exactly one node, but yielded ${result.length}`);
185
185
  fromId = result[0].node.info.id;
186
186
  }
@@ -189,7 +189,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
189
189
  toIds = to.target;
190
190
  }
191
191
  else {
192
- const result = (0, flowr_search_executor_1.runSearch)(to.query, data);
192
+ const result = (0, flowr_search_executor_1.runSearch)(to.query, data).getElements();
193
193
  toIds = result.map(r => r.node.info.id);
194
194
  }
195
195
  return this.edgeHelper(fromId, toIds, type);
@@ -376,7 +376,7 @@ function mergeNodeInfos(current, next) {
376
376
  }
377
377
  else if (current.tag === vertex_1.VertexType.FunctionDefinition) {
378
378
  (0, assert_1.guard)(current.scope === next.scope, 'nodes to be joined for the same id must have the same scope');
379
- (0, assert_1.guard)((0, arrays_1.arrayEqual)(current.exitPoints, next.exitPoints), 'nodes to be joined must have same exist points');
379
+ current.exitPoints = (0, arrays_1.uniqueArrayMerge)(current.exitPoints, next.exitPoints);
380
380
  }
381
381
  return current;
382
382
  }
@@ -0,0 +1,2 @@
1
+ import { DataflowGraph } from './graph';
2
+ export declare function invertDfg(graph: DataflowGraph): DataflowGraph;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.invertDfg = invertDfg;
4
+ const graph_1 = require("./graph");
5
+ function invertDfg(graph) {
6
+ const invertedGraph = new graph_1.DataflowGraph(graph.idMap);
7
+ for (const [, v] of graph.vertices(true)) {
8
+ invertedGraph.addVertex(v);
9
+ }
10
+ for (const [from, targets] of graph.edges()) {
11
+ for (const [to, { types }] of targets) {
12
+ invertedGraph.addEdge(to, from, types);
13
+ }
14
+ }
15
+ return invertedGraph;
16
+ }
17
+ //# sourceMappingURL=invert-dfg.js.map
@@ -25,7 +25,7 @@ async function showQuery(shell, code, queries, { showCode, collapseResult, colla
25
25
  parser: shell,
26
26
  request: (0, retriever_1.requestFromInput)(code)
27
27
  }, config_1.defaultConfigOptions).allRemainingSteps();
28
- const results = (0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries);
28
+ const results = await Promise.resolve((0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries));
29
29
  const duration = performance.now() - now;
30
30
  const metaInfo = `
31
31
  The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing and normalization and the query) within the generation environment.
@@ -53,13 +53,13 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify(search, null, 2))}
53
53
  ${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary>' : ''}
54
54
 
55
55
  The query returns the following vetices (all references to \`x\` in the code):
56
- ${result.map(({ node }) => `<b>${node.info.id} ('${(0, node_id_1.recoverContent)(node.info.id, analysis.dataflow.graph)}')</b> at L${(0, dfg_1.formatRange)(node.location)}`).join(', ')}
56
+ ${result.getElements().map(({ node }) => `<b>${node.info.id} ('${(0, node_id_1.recoverContent)(node.info.id, analysis.dataflow.graph)}')</b> at L${(0, dfg_1.formatRange)(node.location)}`).join(', ')}
57
57
 
58
58
  ${metaInfo}
59
59
 
60
60
  The returned results are highlighted thick and blue within the dataflow graph:
61
61
 
62
- ${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { showCode: false, switchCodeAndGraph: false, mark: new Set(result.map(({ node }) => node.info.id)) })}
62
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { showCode: false, switchCodeAndGraph: false, mark: new Set(result.getElements().map(({ node }) => node.info.id)) })}
63
63
 
64
64
 
65
65
  ${collapseResult ? '</details>' : ''}
@@ -224,8 +224,7 @@ ${Object.entries(control_flow_graph_1.CfgVertexType).map(([key, value]) => `- \`
224
224
  We use the ${(0, doc_types_1.shortLink)('CfgBasicBlockVertex', types.info)} to represent [basic blocks](#cfg-basic-blocks) and separate
225
225
  expressions (${(0, doc_types_1.shortLink)('CfgExpressionVertex', types.info)}) and statements (${(0, doc_types_1.shortLink)('CfgStatementVertex', types.info)})
226
226
  as control flow units with and without side effects (if you want to, you can see view statements as effectful expressions).
227
- The markers (${(0, doc_types_1.shortLink)('CfgMidMarkerVertex', types.info)} and ${(0, doc_types_1.shortLink)('CfgEndMarkerVertex', types.info)})
228
- indicate specific segments of larger expressions/statements (e.g., an \`if\` which has a condition and its branches).
227
+ The markers (${(0, doc_types_1.shortLink)('CfgEndMarkerVertex', types.info)}) indicate the end of larger expressions/statements.
229
228
 
230
229
  To signal these links, the expressions and statements contain information about the attached markers:
231
230
 
@@ -235,7 +234,7 @@ Similarly, the markers contain a link to their root:
235
234
 
236
235
  ${(0, doc_types_1.printHierarchy)({ info: types.info, root: 'CfgWithRoot', program: types.program, openTop: true })}
237
236
 
238
- In mermaid visualizations, we use rectangles for statements, rounded rectangles for expressions, circles for exit markers and double-lined rectangles for mid markers.
237
+ In mermaid visualizations, we use rectangles for statements, rounded rectangles for expressions and circles for exit markers.
239
238
  Blocks are visualized as boxes around the contained vertices.
240
239
 
241
240
  ${(0, doc_structure_1.block)({
@@ -554,7 +553,7 @@ Hence, you may rely on the corresponding exit point(s) to identify all exits of
554
553
 
555
554
  ${(0, doc_structure_1.block)({
556
555
  type: 'WARNING',
557
- content: 'Using basic blocks, this works just the same. However please keep in mind that the corresponding exit markers do not (and for control statements usually will not) be part of the same basic block.'
556
+ content: 'Using basic blocks, this works just the same. However, please keep in mind that the corresponding exit markers do not (and for control statements usually will not) be part of the same basic block.'
558
557
  })}
559
558
 
560
559
  `;
@@ -28,7 +28,6 @@ const built_in_access_1 = require("../dataflow/internal/process/functions/call/b
28
28
  const built_in_for_loop_1 = require("../dataflow/internal/process/functions/call/built-in/built-in-for-loop");
29
29
  const built_in_repeat_loop_1 = require("../dataflow/internal/process/functions/call/built-in/built-in-repeat-loop");
30
30
  const linker_1 = require("../dataflow/internal/linker");
31
- const static_slicer_1 = require("../slicing/static/static-slicer");
32
31
  const info_1 = require("../dataflow/info");
33
32
  const processor_1 = require("../dataflow/processor");
34
33
  const default_pipelines_1 = require("../core/steps/pipeline/default-pipelines");
@@ -42,6 +41,7 @@ const normalize_for_1 = require("../r-bridge/lang-4.x/ast/parser/main/internal/l
42
41
  const doc_issue_1 = require("./doc-util/doc-issue");
43
42
  const pipeline_executor_1 = require("../core/pipeline-executor");
44
43
  const pipeline_1 = require("../core/steps/pipeline/pipeline");
44
+ const static_slicer_1 = require("../slicing/static/static-slicer");
45
45
  const config_1 = require("../config");
46
46
  async function getText(shell) {
47
47
  const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
@@ -373,7 +373,7 @@ Of course, all of these endeavors work not just with the ${(0, doc_types_1.short
373
373
  The slicing is available as an extra step as you can see by inspecting he ${(0, doc_types_1.shortLink)('DEFAULT_SLICING_PIPELINE', info)}.
374
374
  Besides ${(0, doc_types_1.shortLink)('STATIC_SLICE', info)} it contains a ${(0, doc_types_1.shortLink)('NAIVE_RECONSTRUCT', info)} to print the slice as (executable) R code.
375
375
 
376
- Your main point of interesting here is the ${(0, doc_types_1.shortLink)(static_slicer_1.staticSlicing.name, info)} function which relies on a modified
376
+ Your main point of interesting here is the ${(0, doc_types_1.shortLink)(static_slicer_1.staticSlice.name, info)} function which relies on a modified
377
377
  breadth-first search to collect all nodes which are part of the slice.
378
378
  For more information on how the slicing works, please refer to the [tool demonstration (Section 3.2)](https://doi.org/10.1145/3691620.3695359),
379
379
  or the [original master's thesis (Chapter 4)](https://doi.org/10.18725/OPARU-50107).
@@ -835,6 +835,13 @@ The following sections present details on the different types of vertices and ed
835
835
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', 'const node = graph.idMap.get(id);'), '> ')}
836
836
  > In case you just need the name (\`lexeme\`) of the respective vertex, ${(0, doc_types_1.shortLink)(node_id_1.recoverName.name, vertexType.info)} can help you out:
837
837
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', `const name = ${node_id_1.recoverName.name}(id, graph.idMap);`), '> ')}
838
+ >
839
+ > Please note that not every node in the normalized AST is represented in the dataflow graph.
840
+ > For example, if the node is unreachable in a way that can be detected during the analysis and flowR
841
+ > is configured to ignore dead code. Likewise, empty argument wrappers do not have a corresponding
842
+ > dataflow graph vertex (as they are not relevant for the dataflow graph). It depends on the scenario what to do in such a case.
843
+ > For argument wrappers you can access the dataflow information for their value. For dead code, however, flowR currently contains
844
+ > some core heuristics that remove it which cannot be reversed easily. So please open [an issue](${doc_issue_1.NewIssueUrl}) if you encounter such a case and require the node to be present in the dataflow graph.
838
845
 
839
846
  ${(0, doc_structure_1.section)('Vertices', 2, 'vertices')}
840
847
 
@@ -39,6 +39,10 @@ With \`npm\` you have to pass arguments in a specific way. The \`--\` operator i
39
39
  ${(0, doc_code_1.codeBlock)('shell', 'npm run flowR -- --help')}
40
40
  `)}
41
41
 
42
+ ${qAndA('How to do logging in flowR?', `
43
+ Check out the [Logging Section in the Linting and Testing wiki page](${doc_files_1.FlowrWikiBaseRef}/Linting-and-Testing#logging) for more information on how to do logging in *flowR*.
44
+ `)}
45
+
42
46
  ## 🇷 R FAQ
43
47
 
44
48
  ### 📦 R Packages
@@ -20,11 +20,12 @@ const strings_1 = require("../util/text/strings");
20
20
  const assert_1 = require("../util/assert");
21
21
  const doc_print_1 = require("./doc-util/doc-print");
22
22
  const doc_functions_1 = require("./doc-util/doc-functions");
23
+ const linter_format_1 = require("../linter/linter-format");
23
24
  const SpecialTagColors = {
24
25
  [linter_tags_1.LintingRuleTag.Bug]: 'red',
25
26
  [linter_tags_1.LintingRuleTag.Security]: 'orange',
26
27
  [linter_tags_1.LintingRuleTag.Smell]: 'yellow',
27
- [linter_tags_1.LintingRuleTag.QuickFix]: 'lightgray',
28
+ [linter_tags_1.LintingRuleTag.QuickFix]: 'lightgray'
28
29
  };
29
30
  function makeTagBadge(name, info) {
30
31
  const doc = (0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, info, '', true).replaceAll('\n', ' ');
@@ -112,6 +113,7 @@ print(myVar)
112
113
  df <- data.frame(id = 1:5, name = 6:10)
113
114
  df[6, "value"]
114
115
  `, tagTypes);
116
+ rule(shell, 'dead-code', 'DeadCodeConfig', 'DEAD_CODE', 'lint-dead-code', 'if(TRUE) 1 else 2', tagTypes);
115
117
  function rule(shell, name, configType, ruleType, testfile, example, types) {
116
118
  const rule = linter_rules_1.LintingRules[name];
117
119
  const tags = rule.info.tags.toSorted((a, b) => {
@@ -130,6 +132,8 @@ df[6, "value"]
130
132
  }
131
133
  return a.localeCompare(b);
132
134
  }).map(t => makeTagBadge(t, types)).join(' ');
135
+ const certaintyDoc = (0, doc_types_1.getDocumentationForType)(`LintingRuleCertainty::${rule.info.certainty}`, types, '', true).replaceAll('\n', ' ');
136
+ const certaintyText = `\`${(0, html_hover_over_1.textWithTooltip)(rule.info.certainty, certaintyDoc)}\``;
133
137
  if (format === 'short') {
134
138
  ruleExplanations.set(name, () => Promise.resolve(`
135
139
  **[${rule.info.name}](${doc_files_1.FlowrWikiBaseRef}/lint-${name}):** ${rule.info.description} [see ${(0, doc_types_1.shortLinkFile)(ruleType, types)}]\\
@@ -144,6 +148,9 @@ ${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'linte
144
148
  ${(0, doc_structure_1.section)(rule.info.name + `&emsp;<sup>[<a href="${doc_files_1.FlowrWikiBaseRef}/Linter">overview</a>]</sup>`, 2, name)}
145
149
 
146
150
  ${tags}
151
+
152
+
153
+ This rule is a ${certaintyText} rule.
147
154
 
148
155
  ${rule.info.description}\\
149
156
  _This linting rule is implemented in ${(0, doc_types_1.shortLinkFile)(ruleType, types)}._
@@ -171,9 +178,12 @@ ${buildSamplesFromLinterTestCases(shell, `${testfile}.test.ts`)}
171
178
  }
172
179
  return ruleExplanations;
173
180
  }
174
- function getAllLintingRulesWitTag(tag) {
181
+ function getAllLintingRulesWithTag(tag) {
175
182
  return Object.entries(linter_rules_1.LintingRules).filter(([_, rule]) => rule.info.tags.includes(tag)).map(([name]) => name);
176
183
  }
184
+ function getAllLintingRulesWitCertainty(certainty) {
185
+ return Object.entries(linter_rules_1.LintingRules).filter(([_, rule]) => rule.info.certainty === certainty).map(([name]) => name);
186
+ }
177
187
  function linkToRule(name) {
178
188
  return `[${name}](${doc_files_1.FlowrWikiBaseRef}/lint-${name})`;
179
189
  }
@@ -214,14 +224,32 @@ ${await (async () => {
214
224
 
215
225
  ${(0, doc_structure_1.section)('Tags', 2, 'tags')}
216
226
 
217
- We use tags to categorize linting rules. The following tags are available:
227
+ We use tags to categorize linting rules for users. The following tags are available:
218
228
 
219
229
  | Tag/Badge&emsp;&emsp; | Description |
220
230
  | --- | :-- |
221
231
  ${Object.entries(linter_tags_1.LintingRuleTag).map(([name, tag]) => {
222
- return `| <a id="${tag}"></a> ${makeTagBadge(tag, tagTypes.info)} | ${(0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, tagTypes.info).replaceAll(/\n/g, ' ')} (rule${getAllLintingRulesWitTag(tag).length === 1 ? '' : 's'}: ${(0, strings_1.joinWithLast)(getAllLintingRulesWitTag(tag).map(l => linkToRule(l))) || '_none_'}) | `;
232
+ return `| <a id="${tag}"></a> ${(makeTagBadge(tag, tagTypes.info))} | ${(0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, tagTypes.info).replaceAll(/\n/g, ' ')} (rule${getAllLintingRulesWithTag(tag).length === 1 ? '' : 's'}: ${(0, strings_1.joinWithLast)(getAllLintingRulesWithTag(tag).map(l => linkToRule(l))) || '_none_'}) | `;
233
+ }).join('\n')}
234
+
235
+ ${(0, doc_structure_1.section)('Certainty', 2, 'certainty')}
236
+
237
+ Both linting rules and their individual results are additionally categorized by how certain the linter is that the results it is returning are valid.
238
+
239
+ ${(0, doc_structure_1.section)('Rule Certainty', 3, 'rule-certainty')}
240
+
241
+ | Rule Certainty | Description |
242
+ | -------------- | :---------- |
243
+ ${Object.entries(linter_format_1.LintingRuleCertainty).map(([name, certainty]) => {
244
+ return `| <a id="${certainty}"></a> \`${certainty}\` | ${(0, doc_types_1.getDocumentationForType)('LintingRuleCertainty::' + name, tagTypes.info).replaceAll(/\n/g, ' ')} (rule${getAllLintingRulesWitCertainty(certainty).length === 1 ? '' : 's'}: ${(0, strings_1.joinWithLast)(getAllLintingRulesWitCertainty(certainty).map(l => linkToRule(l))) || '_none_'}) |`;
223
245
  }).join('\n')}
224
246
 
247
+ ${(0, doc_structure_1.section)('Result Certainty', 3, 'result-certainty')}
248
+
249
+ | Result Certainty | Description |
250
+ | ---------------- | :---------- |
251
+ ${Object.entries(linter_format_1.LintingResultCertainty).map(([name, certainty]) => `| <a id="${certainty}"></a> \`${certainty}\` | ${(0, doc_types_1.getDocumentationForType)('LintingResultCertainty::' + name, tagTypes.info).replaceAll(/\n/g, ' ')} |`).join('\n')}
252
+
225
253
  `.trim();
226
254
  }
227
255
  async function getRulesPages(shell, tagTypes, rVersion) {
@@ -4,16 +4,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const log_1 = require("../../test/functionality/_helper/log");
7
+ const log_2 = require("../util/log");
7
8
  const doc_code_1 = require("./doc-util/doc-code");
8
9
  const doc_files_1 = require("./doc-util/doc-files");
9
10
  const doc_structure_1 = require("./doc-util/doc-structure");
10
11
  const doc_types_1 = require("./doc-util/doc-types");
11
12
  const path_1 = __importDefault(require("path"));
12
13
  const doc_auto_gen_1 = require("./doc-util/doc-auto-gen");
14
+ const doc_cli_option_1 = require("./doc-util/doc-cli-option");
13
15
  function getText() {
14
16
  const { info } = (0, doc_types_1.getTypesFromFolder)({
15
17
  rootFolder: path_1.default.resolve('./test'),
16
- files: [path_1.default.resolve('./src/dataflow/graph/dataflowgraph-builder.ts')],
18
+ files: [path_1.default.resolve('./src/dataflow/graph/dataflowgraph-builder.ts'), path_1.default.resolve('./src/util/log.ts'), path_1.default.resolve('./src/slicing/static/static-slicer.ts')],
17
19
  typeNameForMermaid: 'parameter',
18
20
  inlineTypes: doc_types_1.mermaidHide
19
21
  });
@@ -39,6 +41,7 @@ for the latest benchmark results, see the [benchmark results](${doc_files_1.Flow
39
41
  - [License Checker](#license-checker)
40
42
  - [🐛 Debugging](#debugging)
41
43
  - [VS Code](#vs-code-1)
44
+ - [Logging](#logging)
42
45
 
43
46
  <a id='testing-suites'></a>
44
47
  ## 🏨 Testing Suites
@@ -254,6 +257,15 @@ However, in case you think that the linter is wrong, please do not hesitate to o
254
257
  ### VS Code
255
258
  When working with VS Code, you can attach a debugger to the REPL. This works automatically by running the \`Start Debugging\` command (\`F5\` by default).
256
259
  You can also set the \`Auto Attach Filter\` setting to automatically attach the debugger, when running \`npm run flowr\`.
260
+
261
+ ### Logging
262
+
263
+ *flowR* uses a wrapper around [tslog](https://www.npmjs.com/package/tslog) using a class named
264
+ ${(0, doc_types_1.shortLink)(log_2.FlowrLogger.name, info)}. They obey to, for example, the ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'verbose')}
265
+ option. Throughout *flowR*, we use the \`log\` object (or subloggers of it) for logging.
266
+ To create your own logger, you can use ${(0, doc_types_1.shortLink)(log_2.FlowrLogger.name + '::' + (new log_2.FlowrLogger().getSubLogger.name), info, true, 'i')}.
267
+ For example, check out the ${(0, doc_types_1.shortLink)('slicerLogger', info)} for the static slicer.
268
+
257
269
  `;
258
270
  }
259
271
  if (require.main === module) {
@@ -13,6 +13,10 @@ To get started developing on *flowR*, we recommend carefully reading the followi
13
13
  - 💖 [Contributing guidelines](${doc_files_1.FlowrGithubBaseRef}/flowr/tree/main/.github/CONTRIBUTING.md).\
14
14
  This page also includes information about how to set up **git-lfs** and several **git hooks**.
15
15
 
16
+ If you have any questions, please check out the [FAQ](${doc_files_1.FlowrWikiBaseRef}/FAQ) first, but if the question
17
+ is not answered there (or in the wiki in general), feel free to ask a question.
18
+
19
+
16
20
  ## ⌛ TL;DR
17
21
 
18
22
  The most important steps to get the *flowR* development environment set up (after installing **R** and **Node.js**) can be seen below. For convenience, they can be executed all at once using the following command: