@eagleoutice/flowr 2.9.11 → 2.9.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.
- package/README.md +20 -20
- package/dataflow/cluster.js +12 -8
- package/dataflow/graph/quads.js +4 -7
- package/dataflow/internal/linker.js +5 -5
- package/documentation/wiki-dataflow-graph.js +86 -31
- package/documentation/wiki-engine.js +18 -0
- package/documentation/wiki-mk/doc-context.d.ts +44 -11
- package/documentation/wiki-mk/doc-context.js +16 -13
- package/package.json +1 -1
- package/queries/catalog/dependencies-query/function-info/library-functions.js +2 -1
- package/queries/catalog/dependencies-query/function-info/read-functions.js +1 -1
- package/queries/catalog/dependencies-query/function-info/visualize-functions.js +9 -1
- package/queries/catalog/dependencies-query/function-info/write-functions.js +1 -0
- package/util/mermaid/dfg.d.ts +8 -0
- package/util/mermaid/dfg.js +4 -0
- package/util/quads.js +14 -6
- package/util/range.d.ts +3 -0
- package/util/range.js +3 -0
- package/util/version.js +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ It offers a wide variety of features, for example:
|
|
|
24
24
|
|
|
25
25
|
```shell
|
|
26
26
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
27
|
-
flowR repl using flowR v2.9.
|
|
27
|
+
flowR repl using flowR v2.9.11, R grammar v14 (tree-sitter engine)
|
|
28
28
|
R> :query @linter "read.csv(\"/root/x.txt\")"
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -35,11 +35,11 @@ It offers a wide variety of features, for example:
|
|
|
35
35
|
```text
|
|
36
36
|
Query: linter (2 ms)
|
|
37
37
|
╰ Deprecated Functions (deprecated-functions):
|
|
38
|
-
╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs:
|
|
38
|
+
╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 1, processTimeMs: 0
|
|
39
39
|
╰ File Path Validity (file-path-validity):
|
|
40
40
|
╰ certain:
|
|
41
41
|
╰ Path `/root/x.txt` at 1.1-23
|
|
42
|
-
╰ Metadata: totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs:
|
|
42
|
+
╰ Metadata: totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 0, processTimeMs: 0
|
|
43
43
|
╰ Seeded Randomness (seeded-randomness):
|
|
44
44
|
╰ Metadata: consumerCalls: 0, callsWithFunctionProducers: 0, callsWithAssignmentProducers: 0, callsWithNonConstantProducers: 0, callsWithOtherBranchProducers: 0, searchTimeMs: 0, processTimeMs: 0
|
|
45
45
|
╰ Absolute Paths (absolute-file-paths):
|
|
@@ -58,7 +58,7 @@ It offers a wide variety of features, for example:
|
|
|
58
58
|
╰ Metadata: consideredNodes: 5, searchTimeMs: 0, processTimeMs: 0
|
|
59
59
|
╰ Useless Loops (useless-loop):
|
|
60
60
|
╰ Metadata: numOfUselessLoops: 0, searchTimeMs: 0, processTimeMs: 0
|
|
61
|
-
All queries together required ≈2 ms (1ms accuracy, total
|
|
61
|
+
All queries together required ≈2 ms (1ms accuracy, total 2 ms)
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
|
|
@@ -80,7 +80,7 @@ It offers a wide variety of features, for example:
|
|
|
80
80
|
|
|
81
81
|
_Results (prettified and summarized):_
|
|
82
82
|
|
|
83
|
-
Query: **linter** (
|
|
83
|
+
Query: **linter** (2 ms)\
|
|
84
84
|
╰ **Deprecated Functions** (deprecated-functions):\
|
|
85
85
|
╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 1, processTimeMs: 0</code>\
|
|
86
86
|
╰ **File Path Validity** (file-path-validity):\
|
|
@@ -88,11 +88,11 @@ It offers a wide variety of features, for example:
|
|
|
88
88
|
╰ Path `/root/x.txt` at 1.1-23\
|
|
89
89
|
╰ _Metadata_: <code>totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
90
90
|
╰ **Seeded Randomness** (seeded-randomness):\
|
|
91
|
-
╰ _Metadata_: <code>consumerCalls: 0, callsWithFunctionProducers: 0, callsWithAssignmentProducers: 0, callsWithNonConstantProducers: 0, callsWithOtherBranchProducers: 0, searchTimeMs:
|
|
91
|
+
╰ _Metadata_: <code>consumerCalls: 0, callsWithFunctionProducers: 0, callsWithAssignmentProducers: 0, callsWithNonConstantProducers: 0, callsWithOtherBranchProducers: 0, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
92
92
|
╰ **Absolute Paths** (absolute-file-paths):\
|
|
93
93
|
╰ certain:\
|
|
94
94
|
╰ Path `/root/x.txt` at 1.1-23\
|
|
95
|
-
╰ _Metadata_: <code>totalConsidered: 1, totalUnknown: 0, searchTimeMs:
|
|
95
|
+
╰ _Metadata_: <code>totalConsidered: 1, totalUnknown: 0, searchTimeMs: 1, processTimeMs: 0</code>\
|
|
96
96
|
╰ **Unused Definitions** (unused-definitions):\
|
|
97
97
|
╰ _Metadata_: <code>totalConsidered: 0, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
98
98
|
╰ **Naming Convention** (naming-convention):\
|
|
@@ -102,14 +102,14 @@ It offers a wide variety of features, for example:
|
|
|
102
102
|
╰ **Dataframe Access Validation** (dataframe-access-validation):\
|
|
103
103
|
╰ _Metadata_: <code>numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
104
104
|
╰ **Dead Code** (dead-code):\
|
|
105
|
-
╰ _Metadata_: <code>consideredNodes: 5, searchTimeMs: 0, processTimeMs:
|
|
105
|
+
╰ _Metadata_: <code>consideredNodes: 5, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
106
106
|
╰ **Useless Loops** (useless-loop):\
|
|
107
107
|
╰ _Metadata_: <code>numOfUselessLoops: 0, searchTimeMs: 0, processTimeMs: 0</code>\
|
|
108
|
-
_All queries together required ≈
|
|
108
|
+
_All queries together required ≈2 ms (1ms accuracy, total 2 ms)_
|
|
109
109
|
|
|
110
110
|
<details> <summary style="color:gray">Show Detailed Results as Json</summary>
|
|
111
111
|
|
|
112
|
-
The analysis required _2.
|
|
112
|
+
The analysis required _2.2 ms_ (including parsing and normalization and the query) within the generation environment.
|
|
113
113
|
|
|
114
114
|
In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR.
|
|
115
115
|
Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those.
|
|
@@ -161,7 +161,7 @@ It offers a wide variety of features, for example:
|
|
|
161
161
|
"callsWithAssignmentProducers": 0,
|
|
162
162
|
"callsWithNonConstantProducers": 0,
|
|
163
163
|
"callsWithOtherBranchProducers": 0,
|
|
164
|
-
"searchTimeMs":
|
|
164
|
+
"searchTimeMs": 0,
|
|
165
165
|
"processTimeMs": 0
|
|
166
166
|
}
|
|
167
167
|
},
|
|
@@ -181,7 +181,7 @@ It offers a wide variety of features, for example:
|
|
|
181
181
|
".meta": {
|
|
182
182
|
"totalConsidered": 1,
|
|
183
183
|
"totalUnknown": 0,
|
|
184
|
-
"searchTimeMs":
|
|
184
|
+
"searchTimeMs": 1,
|
|
185
185
|
"processTimeMs": 0
|
|
186
186
|
}
|
|
187
187
|
},
|
|
@@ -226,7 +226,7 @@ It offers a wide variety of features, for example:
|
|
|
226
226
|
".meta": {
|
|
227
227
|
"consideredNodes": 5,
|
|
228
228
|
"searchTimeMs": 0,
|
|
229
|
-
"processTimeMs":
|
|
229
|
+
"processTimeMs": 0
|
|
230
230
|
}
|
|
231
231
|
},
|
|
232
232
|
"useless-loop": {
|
|
@@ -239,11 +239,11 @@ It offers a wide variety of features, for example:
|
|
|
239
239
|
}
|
|
240
240
|
},
|
|
241
241
|
".meta": {
|
|
242
|
-
"timing":
|
|
242
|
+
"timing": 2
|
|
243
243
|
}
|
|
244
244
|
},
|
|
245
245
|
".meta": {
|
|
246
|
-
"timing":
|
|
246
|
+
"timing": 2
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
```
|
|
@@ -308,7 +308,7 @@ It offers a wide variety of features, for example:
|
|
|
308
308
|
|
|
309
309
|
```shell
|
|
310
310
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
311
|
-
flowR repl using flowR v2.9.
|
|
311
|
+
flowR repl using flowR v2.9.11, R grammar v14 (tree-sitter engine)
|
|
312
312
|
R> :query @static-slice (11@sum) file://test/testfiles/example.R
|
|
313
313
|
```
|
|
314
314
|
|
|
@@ -322,7 +322,7 @@ It offers a wide variety of features, for example:
|
|
|
322
322
|
N <- 10
|
|
323
323
|
for(i in 1:(N-1)) sum <- sum + i + w
|
|
324
324
|
sum
|
|
325
|
-
All queries together required ≈2 ms (1ms accuracy, total
|
|
325
|
+
All queries together required ≈2 ms (1ms accuracy, total 2 ms)
|
|
326
326
|
```
|
|
327
327
|
|
|
328
328
|
|
|
@@ -356,7 +356,7 @@ It offers a wide variety of features, for example:
|
|
|
356
356
|
|
|
357
357
|
|
|
358
358
|
* 🚀 **fast call-graph, data-, and control-flow graphs**\
|
|
359
|
-
Within just [<i><span title="This measurement is automatically fetched from the latest benchmark!">
|
|
359
|
+
Within just [<i><span title="This measurement is automatically fetched from the latest benchmark!">98.9 ms</span></i> (as of Feb 18, 2026)](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark),
|
|
360
360
|
_flowR_ can analyze the data- and control-flow of the average real-world R script. See the [benchmarks](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark) for more information,
|
|
361
361
|
and consult the [wiki pages](https://github.com/flowr-analysis/flowr/wiki/wiki/dataflow-graph) for more details on the [dataflow graphs](https://github.com/flowr-analysis/flowr/wiki/wiki/dataflow-graph) as well as [call graphs](https://github.com/flowr-analysis/flowr/wiki/wiki/dataflow-graph#perspectives-cg).
|
|
362
362
|
|
|
@@ -392,7 +392,7 @@ It offers a wide variety of features, for example:
|
|
|
392
392
|
|
|
393
393
|
```shell
|
|
394
394
|
$ docker run -it --rm eagleoutice/flowr # or npm run flowr
|
|
395
|
-
flowR repl using flowR v2.9.
|
|
395
|
+
flowR repl using flowR v2.9.11, R grammar v14 (tree-sitter engine)
|
|
396
396
|
R> :dataflow* test/testfiles/example.R
|
|
397
397
|
```
|
|
398
398
|
|
|
@@ -700,7 +700,7 @@ It offers a wide variety of features, for example:
|
|
|
700
700
|
```
|
|
701
701
|
|
|
702
702
|
|
|
703
|
-
(The analysis required
|
|
703
|
+
(The analysis required _1.6 ms_ (including parse and normalize, using the [tree-sitter](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
|
|
704
704
|
|
|
705
705
|
|
|
706
706
|
|
package/dataflow/cluster.js
CHANGED
|
@@ -30,18 +30,22 @@ function makeCluster(graph, from, notReached) {
|
|
|
30
30
|
if (info.tag === vertex_1.VertexType.FunctionDefinition) {
|
|
31
31
|
for (const { nodeId } of info.exitPoints) {
|
|
32
32
|
if (notReached.delete(nodeId)) {
|
|
33
|
-
makeCluster(graph, nodeId, notReached)
|
|
33
|
+
for (const m of makeCluster(graph, nodeId, notReached)) {
|
|
34
|
+
nodes.add(m);
|
|
35
|
+
}
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
// cluster adjacent edges
|
|
38
|
-
for (const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
for (const edges of [graph.outgoingEdges(from), graph.ingoingEdges(from)]) {
|
|
41
|
+
for (const [dest, e] of edges ?? []) {
|
|
42
|
+
// don't cluster for function content if it isn't returned
|
|
43
|
+
if (edge_1.DfEdge.doesNotIncludeType(e, edge_1.EdgeType.Returns) && info.onlyBuiltin && info.name === '{') {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (notReached.delete(dest)) {
|
|
47
|
+
makeCluster(graph, dest, notReached).forEach(n => nodes.add(n));
|
|
48
|
+
}
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
return nodes;
|
package/dataflow/graph/quads.js
CHANGED
|
@@ -10,13 +10,10 @@ const edge_1 = require("./edge");
|
|
|
10
10
|
*/
|
|
11
11
|
function df2quads(graph, config) {
|
|
12
12
|
return (0, quads_1.graph2quads)({
|
|
13
|
-
rootIds:
|
|
14
|
-
vertices: graph.vertices(true)
|
|
15
|
-
.map(([
|
|
16
|
-
|
|
17
|
-
id
|
|
18
|
-
})).toArray(),
|
|
19
|
-
edges: graph.edges().flatMap(([fromId, targets]) => [...targets].map(([toId, info]) => ({
|
|
13
|
+
rootIds: Array.from(graph.rootIds()),
|
|
14
|
+
vertices: Array.from(graph.vertices(true)
|
|
15
|
+
.map(([, v]) => v)),
|
|
16
|
+
edges: graph.edges().flatMap(([fromId, targets]) => Array.from(targets).map(([toId, info]) => ({
|
|
20
17
|
from: fromId,
|
|
21
18
|
to: toId,
|
|
22
19
|
type: Array.from(edge_1.DfEdge.typesToNames(info)),
|
|
@@ -395,18 +395,18 @@ function getAllLinkedFunctionDefinitions(functionDefinitionReadIds, dataflowGrap
|
|
|
395
395
|
builtIns.add(cid);
|
|
396
396
|
continue;
|
|
397
397
|
}
|
|
398
|
-
const
|
|
399
|
-
if (
|
|
398
|
+
const vertex = dataflowGraph.getVertex(cid);
|
|
399
|
+
if (vertex === undefined) {
|
|
400
400
|
continue;
|
|
401
401
|
}
|
|
402
|
-
const [vertex, edges] = currentInfo;
|
|
403
402
|
// Found a function definition
|
|
404
403
|
if (vertex.subflow !== undefined) {
|
|
405
404
|
result.add(vertex);
|
|
406
405
|
continue;
|
|
407
406
|
}
|
|
408
407
|
let hasReturnEdge = false;
|
|
409
|
-
|
|
408
|
+
const outgoing = dataflowGraph.outgoingEdges(cid) ?? [];
|
|
409
|
+
for (const [target, e] of outgoing) {
|
|
410
410
|
if (edge_1.DfEdge.includesType(e, edge_1.EdgeType.Returns)) {
|
|
411
411
|
hasReturnEdge = true;
|
|
412
412
|
if (!visited.has(target)) {
|
|
@@ -417,7 +417,7 @@ function getAllLinkedFunctionDefinitions(functionDefinitionReadIds, dataflowGrap
|
|
|
417
417
|
if (vertex.tag === vertex_1.VertexType.FunctionCall || hasReturnEdge || (vertex.tag === vertex_1.VertexType.VariableDefinition && vertex.par)) {
|
|
418
418
|
continue;
|
|
419
419
|
}
|
|
420
|
-
for (const [target, e] of
|
|
420
|
+
for (const [target, e] of outgoing) {
|
|
421
421
|
if (edge_1.DfEdge.includesType(e, LinkedFnFollowBits) && !visited.has(target)) {
|
|
422
422
|
potential.push(target);
|
|
423
423
|
}
|
|
@@ -39,6 +39,10 @@ const flowr_analyzer_context_1 = require("../project/context/flowr-analyzer-cont
|
|
|
39
39
|
const doc_maker_1 = require("./wiki-mk/doc-maker");
|
|
40
40
|
const flowr_analyzer_1 = require("../project/flowr-analyzer");
|
|
41
41
|
const built_in_1 = require("../dataflow/environments/built-in");
|
|
42
|
+
const dfg_1 = require("../util/mermaid/dfg");
|
|
43
|
+
const r_number_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-number");
|
|
44
|
+
const model_1 = require("../r-bridge/lang-4.x/ast/model/model");
|
|
45
|
+
const range_1 = require("../util/range");
|
|
42
46
|
async function subExplanation(parser, { description, code, expectedSubgraph }) {
|
|
43
47
|
expectedSubgraph = await (0, doc_dfg_1.verifyExpectedSubgraph)(parser, code, expectedSubgraph);
|
|
44
48
|
const marks = [];
|
|
@@ -741,12 +745,14 @@ class WikiDataflowGraph extends doc_maker_1.DocMaker {
|
|
|
741
745
|
super('wiki/Dataflow Graph.md', module.filename, 'dataflow graph');
|
|
742
746
|
}
|
|
743
747
|
async text({ ctx, treeSitter }) {
|
|
748
|
+
const introExampleCode = 'x <- 3\ny <- x + 1\ny';
|
|
744
749
|
return `
|
|
745
|
-
This page briefly summarizes flowR's dataflow graph
|
|
746
|
-
In case you want to manually build such a graph (e.g., for testing), you can use the ${ctx.link(dataflowgraph_builder_1.DataflowGraphBuilder)}.
|
|
750
|
+
This page briefly summarizes flowR's dataflow graph (${ctx.link(graph_1.DataflowGraph)}).
|
|
747
751
|
If you are interested in which features we support and which features are still to be worked on, please refer to our ${ctx.linkPage('wiki/Capabilities')} page.
|
|
748
|
-
In
|
|
752
|
+
In case you want to manually build such a graph (e.g., for testing), you can use the ${ctx.link(dataflowgraph_builder_1.DataflowGraphBuilder)}.
|
|
753
|
+
In summary, we discuss the following topics in this wiki page:
|
|
749
754
|
|
|
755
|
+
- [Reading the Visualization](#reading-the-visualization)
|
|
750
756
|
- [Vertices](#vertices)
|
|
751
757
|
- [Edges](#edges)
|
|
752
758
|
- [Control Dependencies](#control-dependencies)
|
|
@@ -756,37 +762,35 @@ In summary, we discuss the following topics:
|
|
|
756
762
|
- [Call Graph Perspective](#perspectives-cg)
|
|
757
763
|
- [Working with the Dataflow Graph](#dfg-working)
|
|
758
764
|
|
|
759
|
-
Please be aware that the accompanied [dataflow information](#dataflow-information) (${ctx.link('DataflowInformation')}) returned by _flowR_
|
|
760
|
-
like the entry and exit points of the subgraphs, and currently active references (see [below](#dataflow-information)).
|
|
761
|
-
Additionally, you may be interested in the
|
|
762
|
-
|
|
763
|
-
Potentially, you are interested in another perspective that flowR provides, the [control flow graph](${doc_files_1.FlowrWikiBaseRef}/Control%20Flow%20Graph), so please check the correpsonding
|
|
764
|
-
wiki page if you are unsure.
|
|
765
|
+
Please be aware that the accompanied [dataflow information](#dataflow-information) (${ctx.link('DataflowInformation')}) returned by _flowR_
|
|
766
|
+
contains things besides the graph, like the entry and exit points of the subgraphs, and currently active references (see [below](#dataflow-information)).
|
|
767
|
+
Additionally, you may be interested in the [Unknown Side Effects](#unknown-side-effects), marking calls which _flowR_ is unable to handle correctly.
|
|
765
768
|
|
|
766
769
|
> [!TIP]
|
|
767
|
-
>
|
|
768
|
-
> you can either use the
|
|
769
|
-
> command in the REPL (see the ${ctx.linkPage('wiki/Interface', 'Interface wiki page')}
|
|
770
|
-
> There is also a simplified
|
|
770
|
+
> To investigate the dataflow graph,
|
|
771
|
+
> you can either use the ${ctx.linkPage('flowr:vscode')} or the ${ctx.replCmd('dataflow*')}
|
|
772
|
+
> command in the REPL (see the ${ctx.linkPage('wiki/Interface', 'Interface wiki page')}).
|
|
773
|
+
> There is also a simplified version available with ${ctx.replCmd('dataflowsimple*')} that does not show everything but is easier to read.
|
|
771
774
|
> For small graphs, you can also use ${ctx.replCmd('dataflowascii')} to print the graph as ASCII art.
|
|
772
|
-
>
|
|
773
|
-
> When using _flowR_ as a library, you may use the functions in ${(0, doc_files_1.getFilePathMd)('../util/mermaid/dfg.ts')}.
|
|
774
775
|
>
|
|
775
|
-
> If you receive a dataflow graph in its serialized form (e.g., by talking to a [_flowR_ server](${doc_files_1.FlowrWikiBaseRef}/Interface)), you can use ${ctx.linkM(graph_1.DataflowGraph, 'fromJson', { realNameWrapper: 'i', codeFont: true })} to
|
|
776
|
+
> If you receive a dataflow graph in its serialized form (e.g., by talking to a [_flowR_ server](${doc_files_1.FlowrWikiBaseRef}/Interface)), you can use ${ctx.linkM(graph_1.DataflowGraph, 'fromJson', { realNameWrapper: 'i', codeFont: true })} to recover the graph object.
|
|
776
777
|
>
|
|
777
778
|
> Also, check out the [${doc_files_1.FlowrGithubGroupName}/sample-analyzer-df-diff](${doc_files_1.FlowrGithubBaseRef}/sample-analyzer-df-diff) repository for a complete example project creating and comparing dataflow graphs.
|
|
778
779
|
|
|
779
|
-
|
|
780
|
+
To get started, let's look at the graph for the following code snippet:
|
|
781
|
+
${(0, doc_code_1.codeBlock)('r', introExampleCode)}
|
|
780
782
|
|
|
783
|
+
With this code, the corresponding dataflow graph looks like this:
|
|
781
784
|
|
|
782
|
-
|
|
783
|
-
|
|
785
|
+
${await (0, doc_dfg_1.printDfGraphForCode)(treeSitter, introExampleCode, { showCode: false })}
|
|
786
|
+
|
|
787
|
+
The above dataflow graph showcases the general gist. We define a dataflow graph as a directed graph G = (V, E),
|
|
788
|
+
differentiating between ${(0, doc_data_dfg_util_1.getAllVertices)().length} types of vertices V and
|
|
789
|
+
${(0, doc_data_dfg_util_1.getAllEdges)().length} types of edges E allowing each vertex to have a single, and each edge to have multiple distinct types.
|
|
784
790
|
Additionally, every node may have links to its [control dependencies](#control-dependencies) (which you may view as a ${(0, text_1.nth)((0, doc_data_dfg_util_1.getAllEdges)().length + 1)} edge type,
|
|
785
791
|
although they are explicitly no data dependency and relate to the ${ctx.linkPage('wiki/Control Flow Graph')}.
|
|
786
792
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
<summary>Vertex Types</summary>
|
|
793
|
+
${(0, doc_structure_1.details)('Simplified Version of the graph', await (0, doc_dfg_1.printDfGraphForCode)(treeSitter, 'x <- 3\ny <- x + 1\ny', { simplified: true, showCode: false }))}
|
|
790
794
|
|
|
791
795
|
The following vertices types exist:
|
|
792
796
|
|
|
@@ -794,20 +798,13 @@ The following vertices types exist:
|
|
|
794
798
|
|
|
795
799
|
${(0, doc_structure_1.details)('Class Diagram', 'All boxes should link to their respective implementation:\n' + (0, doc_code_1.codeBlock)('mermaid', ctx.mermaid('DataflowGraphVertexInfo', { inlineTypes: ['MergeableRecord'] })))}
|
|
796
800
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
<details open>
|
|
800
|
-
|
|
801
|
-
<summary>Edge Types</summary>
|
|
802
|
-
|
|
803
|
-
The following edges types exist, internally we use bitmasks to represent multiple types in a compact form:
|
|
801
|
+
The following edges types exist, internally we use bitmasks to represent multiple types in a compact form, so you
|
|
802
|
+
should use the ${ctx.link('DfEdge', { codeFont: false, realNameWrapper: 'i' }, { type: 'variable' })} object and its methods to work with them:
|
|
804
803
|
|
|
805
804
|
1. ${(0, doc_data_dfg_util_1.getAllEdges)().map(([k, v], index) => `[\`${k}\` (${v})](#${index + 1}-${k.toLowerCase().replace(/\s/g, '-')}-edge)`).join('\n1. ')}
|
|
806
805
|
|
|
807
806
|
${(0, doc_structure_1.details)('Class Diagram', 'All boxes should link to their respective implementation:\n' + (0, doc_code_1.codeBlock)('mermaid', ctx.mermaid('EdgeType', { inlineTypes: ['MergeableRecord'] })))}
|
|
808
807
|
|
|
809
|
-
</details>
|
|
810
|
-
|
|
811
808
|
|
|
812
809
|
From an implementation perspective all of these types are represented by respective interfaces, see ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/vertex.ts')} and ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/edge.ts')}.
|
|
813
810
|
|
|
@@ -828,6 +825,64 @@ ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', `const name = $
|
|
|
828
825
|
> For argument wrappers you can access the dataflow information for their value. For dead code, however, flowR currently contains
|
|
829
826
|
> 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.
|
|
830
827
|
|
|
828
|
+
${(0, doc_structure_1.section)('Reading the Visualizations', 2, 'reading-the-visualization')}
|
|
829
|
+
|
|
830
|
+
Before we dive into the details of the different vertices and edges, let's briefly talk about how to read the visualizations.
|
|
831
|
+
For this, let's have a look at a very simple graph, created for the number \`42\`:
|
|
832
|
+
|
|
833
|
+
${await (0, doc_dfg_1.printDfGraphForCode)(treeSitter, '42', { showCode: false })}
|
|
834
|
+
|
|
835
|
+
${(0, doc_structure_1.section)('Vertex Shape', 3, 'vtx-shape')}
|
|
836
|
+
|
|
837
|
+
The _shape_ of the vertex tells you the type of the vertex in the dataflow graph using the following scheme (the types are
|
|
838
|
+
explained in more detail in the following sections):
|
|
839
|
+
|
|
840
|
+
${(0, doc_code_1.codeBlock)('mermaid', 'flowchart TD\n' +
|
|
841
|
+
// use mermaidNodeBrackets to get open and closing bracket
|
|
842
|
+
Object.entries(vertex_1.VertexType)
|
|
843
|
+
.map(([k, v]) => {
|
|
844
|
+
const { open, close } = (0, dfg_1.mermaidNodeBrackets)(v);
|
|
845
|
+
return ` ${v}${open}${k}${close}`;
|
|
846
|
+
}).join('\n') +
|
|
847
|
+
// we add a subflow for the function definition
|
|
848
|
+
'\n subgraph fbox ["function body"]\n body((...))\n end\n fdef-->fbox')}
|
|
849
|
+
|
|
850
|
+
${(0, doc_structure_1.section)('Syntactic Types', 3, 'vtx-synt-type')}
|
|
851
|
+
|
|
852
|
+
Within the shape, in square brackets, you can find the syntactic type of the vertex
|
|
853
|
+
which is linked to the node in the ${ctx.linkPage('wiki/Normalized AST')}.
|
|
854
|
+
For more information on valid types and what to do with them, please refer to the ${ctx.linkPage('wiki/Normalized AST', 'normalized AST wiki page')}
|
|
855
|
+
and the corresponding helper objects (e.g., ${ctx.link(r_number_1.RNumber, undefined, { type: 'variable' })}).
|
|
856
|
+
|
|
857
|
+
${(0, doc_structure_1.section)('Lexeme', 3, 'vtx-lexeme')}
|
|
858
|
+
|
|
859
|
+
Also in the first line, next to the [syntactic type](#vtx-synt-type), you can find the lexeme of the vertex (if it has one, e.g., for a variable definition or use).
|
|
860
|
+
This usually represents the textual source string of the respective vertex, and is also linked to the ${ctx.linkPage('wiki/Normalized AST')}.
|
|
861
|
+
You can access the lexeme too with ${ctx.linkO(model_1.RNode, 'lexeme')}.
|
|
862
|
+
|
|
863
|
+
${(0, doc_structure_1.section)('Vertex Id', 3, 'vtx-id')}
|
|
864
|
+
|
|
865
|
+
In the second line, you will usually find the id (in the form of a ${ctx.link(node_id_1.NodeId, undefined, { type: 'variable' })}) of the vertex,
|
|
866
|
+
alongside its [control dependencies](#control-dependencies) if it has any. This id links the vertex to the respective node in the ${ctx.linkPage('wiki/Normalized AST')} (and all other perspectives created by flowR).
|
|
867
|
+
To give you an example, have a look at the following graph:
|
|
868
|
+
|
|
869
|
+
${await (0, doc_dfg_1.printDfGraphForCode)(treeSitter, 'if(u) a', { showCode: false, mark: new Set(['1']) })}
|
|
870
|
+
With the _may_ prefix you can see that \`a\` has a [control dependency](#control-dependencies)
|
|
871
|
+
on the \`if\`, which only triggers when the condition is \`true\` (as indicated by the \`+\` suffix).
|
|
872
|
+
|
|
873
|
+
${(0, doc_structure_1.section)('Location', 3, 'vtx-location')}
|
|
874
|
+
|
|
875
|
+
The third line indicates the compressed ${ctx.link(range_1.SourceRange)} of the vertex in the format \`startLine.startCharacter - endLine.endCharacter\`. If the range reads \`1.7\`,
|
|
876
|
+
this is short for \`1.7-1.7\`, likewise, \`1.7-9\` is short for \`1.7-1.9\`. So, \`1.7-9\` describes something starting
|
|
877
|
+
in the first line at the seventh character and ending in the first line at the ninth character.
|
|
878
|
+
|
|
879
|
+
${(0, doc_structure_1.section)('Arguments and Additional Information', 3, 'vtx-additional-info')}
|
|
880
|
+
|
|
881
|
+
Some vertices (e.g., [function calls](#function-call-vertex)) have additional information, like the arguments of the call.
|
|
882
|
+
As you can see with the \`if\` example above alongside the [vertex id](#vtx-id),
|
|
883
|
+
these vertices also have an additional line which lists the ids of the arguments in order to clear any ambiguity in case, for example,
|
|
884
|
+
the mermaid graph layouting fumbles the order.
|
|
885
|
+
|
|
831
886
|
${(0, doc_structure_1.section)('Vertices', 2, 'vertices')}
|
|
832
887
|
|
|
833
888
|
1. ${(0, doc_data_dfg_util_1.getAllVertices)().map(([k, v]) => `[\`${k}\`](#${v.toLowerCase().replaceAll(/\s/g, '-')}-vertex)`).join('\n1. ')}
|
|
@@ -37,6 +37,19 @@ are exposed with some command line options (e.g., when using the docker image of
|
|
|
37
37
|
- ${ctx.cliOption('flowr', 'engine.tree-sitter.tree-sitter-wasm-path', false)} pass the path to the wasm of tree-sitter (see [below](#tree-sitter))
|
|
38
38
|
- ${ctx.cliOption('flowr', 'default-engine', false)} to set the default engine to use
|
|
39
39
|
|
|
40
|
+
<a id="r-shell"></a>
|
|
41
|
+
## Dealing with the R Shell Engine
|
|
42
|
+
|
|
43
|
+
The ${ctx.link(shell_1.RShell)} engine is the original engine of flowR and is still available today.
|
|
44
|
+
It provides a powerful interface to the R interpreter, allowing for complex interactions and the execution of R code.
|
|
45
|
+
There are two interfaces available:
|
|
46
|
+
|
|
47
|
+
* The ${ctx.link(shell_1.RShell)} which is asynchronous and allows for non-blocking interactions with the R interpreter. This is the default engine.
|
|
48
|
+
* The ${ctx.link(shell_executor_1.RShellExecutor)} which is synchronous and blocks the execution until the R code is executed. This can be useful for certain use cases where you want to ensure that the R code is executed before proceeding with the analysis.
|
|
49
|
+
|
|
50
|
+
Please note, that these classes are available to you even if you do not use/enable the R shell engine.
|
|
51
|
+
The selection and preparation of the engine just reflects what the flowR analysis will use.
|
|
52
|
+
|
|
40
53
|
<a id="tree-sitter"></a>
|
|
41
54
|
## Dealing with the Tree-Sitter Engine
|
|
42
55
|
|
|
@@ -59,6 +72,11 @@ you first must build the new wasm file. For this you have to:
|
|
|
59
72
|
3. Pass the \`tree-sitter-r.wasm\` to flowR.
|
|
60
73
|
|
|
61
74
|
For tree-sitter, please rely on the [releases](https://github.com/tree-sitter/tree-sitter/releases).
|
|
75
|
+
|
|
76
|
+
${(0, doc_structure_1.block)({
|
|
77
|
+
type: 'NOTE',
|
|
78
|
+
content: 'The tree-sitter grammar may not be able to parse all valid R code due to some bugs in the parser grammar. In that case, please report these to the [tree-sitter-r repository](https://github.com/r-lib/tree-sitter-r).'
|
|
79
|
+
})}
|
|
62
80
|
`;
|
|
63
81
|
}
|
|
64
82
|
}
|
|
@@ -47,17 +47,50 @@ type StaticKeys<T> = T extends {
|
|
|
47
47
|
prototype: infer P;
|
|
48
48
|
} ? Exclude<keyof T, keyof P> : never;
|
|
49
49
|
export declare const ConstantWikiLinkInfo: {
|
|
50
|
-
readonly 'flowr:npm':
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
readonly 'flowr:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
readonly 'flowr:
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
readonly 'flowr:npm': {
|
|
51
|
+
readonly url: "https://www.npmjs.com/package/@eagleoutice/flowr";
|
|
52
|
+
readonly name: "flowR on npm";
|
|
53
|
+
};
|
|
54
|
+
readonly 'flowr:github': {
|
|
55
|
+
readonly url: string;
|
|
56
|
+
readonly name: "flowR's GitHub";
|
|
57
|
+
};
|
|
58
|
+
readonly 'flowr:wiki': {
|
|
59
|
+
readonly url: "https://github.com/flowr-analysis/flowr/wiki";
|
|
60
|
+
readonly name: "flowR's wiki";
|
|
61
|
+
};
|
|
62
|
+
readonly 'flowr:docker': {
|
|
63
|
+
readonly url: "https://hub.docker.com/r/eagleoutice/flowr";
|
|
64
|
+
readonly name: "flowR's Docker Image";
|
|
65
|
+
};
|
|
66
|
+
readonly 'flowr:vscode': {
|
|
67
|
+
readonly url: "https://marketplace.visualstudio.com/items?itemName=code-inspect.vscode-flowr";
|
|
68
|
+
readonly name: "flowR extension for VS Code";
|
|
69
|
+
};
|
|
70
|
+
readonly 'flowr:positron': {
|
|
71
|
+
readonly url: "https://open-vsx.org/extension/code-inspect/vscode-flowr";
|
|
72
|
+
readonly name: "flowR extension for Positron";
|
|
73
|
+
};
|
|
74
|
+
readonly 'flowr:rstudio-addin': {
|
|
75
|
+
readonly url: "https://github.com/flowr-analysis/rstudio-addin-flowr";
|
|
76
|
+
readonly name: "flowR RStudio Addin";
|
|
77
|
+
};
|
|
78
|
+
readonly 'flowr:radapter': {
|
|
79
|
+
readonly url: "https://github.com/flowr-analysis/flowr-r-adapter";
|
|
80
|
+
readonly name: "flowR R Adapter";
|
|
81
|
+
};
|
|
82
|
+
readonly 'flowr:benchmarks': {
|
|
83
|
+
readonly url: "https://flowr-analysis.github.io/flowr/wiki/stats/benchmark";
|
|
84
|
+
readonly name: "flowR benchmark page";
|
|
85
|
+
};
|
|
86
|
+
readonly 'flowr:docs': {
|
|
87
|
+
readonly url: "https://flowr-analysis.github.io/flowr/docs";
|
|
88
|
+
readonly name: "flowR code docs";
|
|
89
|
+
};
|
|
90
|
+
readonly 'flowr:zenodo': {
|
|
91
|
+
readonly url: "https://zenodo.org/doi/10.5281/zenodo.13319290";
|
|
92
|
+
readonly name: "flowR on Zenodo";
|
|
93
|
+
};
|
|
61
94
|
};
|
|
62
95
|
/**
|
|
63
96
|
* Provides methods to generate links, code snippets, and documentation for code elements.
|
|
@@ -23,17 +23,17 @@ function getNameFromElementIdOrRef(element) {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
exports.ConstantWikiLinkInfo = {
|
|
26
|
-
'flowr:npm': doc_files_1.FlowrNpmRef,
|
|
27
|
-
'flowr:github': doc_files_1.FlowrGithubRef,
|
|
28
|
-
'flowr:wiki': doc_files_1.FlowrWikiBaseRef,
|
|
29
|
-
'flowr:docker': doc_files_1.FlowrDockerRef,
|
|
30
|
-
'flowr:vscode': doc_files_1.FlowrVsCode,
|
|
31
|
-
'flowr:positron': doc_files_1.FlowrPositron,
|
|
32
|
-
'flowr:rstudio-addin': doc_files_1.FlowrRStudioAddin,
|
|
33
|
-
'flowr:radapter': doc_files_1.FlowrRAdapter,
|
|
34
|
-
'flowr:benchmarks': 'https://flowr-analysis.github.io/flowr/wiki/stats/benchmark',
|
|
35
|
-
'flowr:docs': 'https://flowr-analysis.github.io/flowr/docs',
|
|
36
|
-
'flowr:zenodo': 'https://zenodo.org/doi/10.5281/zenodo.13319290'
|
|
26
|
+
'flowr:npm': { url: doc_files_1.FlowrNpmRef, name: 'flowR on npm' },
|
|
27
|
+
'flowr:github': { url: doc_files_1.FlowrGithubRef, name: 'flowR\'s GitHub' },
|
|
28
|
+
'flowr:wiki': { url: doc_files_1.FlowrWikiBaseRef, name: 'flowR\'s wiki' },
|
|
29
|
+
'flowr:docker': { url: doc_files_1.FlowrDockerRef, name: 'flowR\'s Docker Image' },
|
|
30
|
+
'flowr:vscode': { url: doc_files_1.FlowrVsCode, name: 'flowR extension for VS Code' },
|
|
31
|
+
'flowr:positron': { url: doc_files_1.FlowrPositron, name: 'flowR extension for Positron' },
|
|
32
|
+
'flowr:rstudio-addin': { url: doc_files_1.FlowrRStudioAddin, name: 'flowR RStudio Addin' },
|
|
33
|
+
'flowr:radapter': { url: doc_files_1.FlowrRAdapter, name: 'flowR R Adapter' },
|
|
34
|
+
'flowr:benchmarks': { url: 'https://flowr-analysis.github.io/flowr/wiki/stats/benchmark', name: 'flowR benchmark page' },
|
|
35
|
+
'flowr:docs': { url: 'https://flowr-analysis.github.io/flowr/docs', name: 'flowR code docs' },
|
|
36
|
+
'flowr:zenodo': { url: 'https://zenodo.org/doi/10.5281/zenodo.13319290', name: 'flowR on Zenodo' },
|
|
37
37
|
};
|
|
38
38
|
/**
|
|
39
39
|
* Creates a wiki context for generating documentation for code elements.
|
|
@@ -100,14 +100,17 @@ function makeDocContextForTypes(shell, ...rootFolders) {
|
|
|
100
100
|
});
|
|
101
101
|
},
|
|
102
102
|
linkPage(pageName, linkText, segment) {
|
|
103
|
-
const text = linkText ?? pageName.split('/').pop() ?? pageName;
|
|
104
103
|
let link;
|
|
104
|
+
let text = linkText;
|
|
105
105
|
if (pageName in exports.ConstantWikiLinkInfo) {
|
|
106
|
-
|
|
106
|
+
const i = exports.ConstantWikiLinkInfo[pageName];
|
|
107
|
+
link = i.url;
|
|
108
|
+
text ??= i.name;
|
|
107
109
|
}
|
|
108
110
|
else {
|
|
109
111
|
link = `${doc_files_1.FlowrWikiBaseRef}/${pageName.toLowerCase().replace(/ /g, '-')}`;
|
|
110
112
|
}
|
|
113
|
+
text ??= pageName.split('/').pop() ?? pageName;
|
|
111
114
|
return `[${text}](${link}${segment ? `#${segment}` : ''})`;
|
|
112
115
|
},
|
|
113
116
|
linkCode(path, lineNumber) {
|
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@ exports.LibraryFunctions = [
|
|
|
13
13
|
{ package: 'easypackages', name: 'from_import', argIdx: 0, argName: 'package', resolveValue: true },
|
|
14
14
|
{ package: 'easypackages', name: 'libraries', argIdx: 'unnamed', resolveValue: true },
|
|
15
15
|
{ package: 'librarian', name: 'shelf', argIdx: 'unnamed', resolveValue: true },
|
|
16
|
-
{ package: 'devtools', name: 'load_all', argIdx: 0, argName: 'path', resolveValue: true }
|
|
16
|
+
{ package: 'devtools', name: 'load_all', argIdx: 0, argName: 'path', resolveValue: true, defaultValue: '.' },
|
|
17
|
+
{ package: 'devtools', name: 'load_code', argIdx: 0, argName: 'path', resolveValue: true, defaultValue: '.' },
|
|
17
18
|
];
|
|
18
19
|
//# sourceMappingURL=library-functions.js.map
|
|
@@ -93,7 +93,7 @@ exports.ReadFunctions = [
|
|
|
93
93
|
{ package: 'XLConnect', name: 'loadWorkbook', argIdx: 0, argName: 'filename', resolveValue: true },
|
|
94
94
|
{ package: 'DiagrammeR', name: 'import_graph', argIdx: 0, argName: 'graph_file', resolveValue: true },
|
|
95
95
|
{ package: 'DiagrammeR', name: 'open_graph', argIdx: 0, argName: 'file', resolveValue: true },
|
|
96
|
-
{ package: 'highcharter', name: 'download_map_data', argIdx: 0, argName: 'url', resolveValue: true },
|
|
96
|
+
{ package: 'highcharter', name: 'download_map_data', argIdx: 0, argName: 'url', resolveValue: true, defaultValue: 'custom/world.js' },
|
|
97
97
|
{ package: 'rvest', name: 'read_html', argIdx: 0, argName: 'x', resolveValue: true },
|
|
98
98
|
{ package: 'rvest', name: 'read_html_live', argIdx: 0, argName: 'url', resolveValue: true },
|
|
99
99
|
{ package: 'stats', name: 'read.ftable', argIdx: 0, argName: 'file', resolveValue: true },
|
|
@@ -9,5 +9,13 @@ exports.VisualizeFunctions =
|
|
|
9
9
|
// plot creation
|
|
10
10
|
default_builtin_config_1.GgPlotCreate.map(f => ({ package: 'ggplot2', name: f })).concat(default_builtin_config_1.TinyPlotCrate.map(f => ({ package: 'tinyplot', name: f })), default_builtin_config_1.GraphicsPlotCreate.map(f => ({ name: f })),
|
|
11
11
|
// plot modification
|
|
12
|
-
default_builtin_config_1.GgPlotImplicitAddons.concat(default_builtin_config_1.GgPlotAddons).map(f => ({ package: 'ggplot2', name: f, linkTo: LinkToPlotCreation })), default_builtin_config_1.TinyPlotAddons.map(f => ({ package: 'tinyplot', name: f, linkTo: LinkToPlotCreation })), default_builtin_config_1.GraphicsPlotAddons.map(f => ({ name: f, linkTo: LinkToPlotCreation })))
|
|
12
|
+
default_builtin_config_1.GgPlotImplicitAddons.concat(default_builtin_config_1.GgPlotAddons).map(f => ({ package: 'ggplot2', name: f, linkTo: LinkToPlotCreation })), default_builtin_config_1.TinyPlotAddons.map(f => ({ package: 'tinyplot', name: f, linkTo: LinkToPlotCreation })), default_builtin_config_1.GraphicsPlotAddons.map(f => ({ name: f, linkTo: LinkToPlotCreation }))).map(f => {
|
|
13
|
+
if (f.name !== 'hist') {
|
|
14
|
+
return f;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// ignore if plot is false.
|
|
18
|
+
return { ...f, ignoreIf: 'arg-false', additionalArgs: { val: { argIdx: 17, argName: 'plot', resolveValue: true } } };
|
|
19
|
+
}
|
|
20
|
+
});
|
|
13
21
|
//# sourceMappingURL=visualize-functions.js.map
|
|
@@ -115,5 +115,6 @@ 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: 'magick', name: 'image_write', argIdx: 1, argName: 'path', resolveValue: true, ignoreIf: 'arg-missing' },
|
|
118
119
|
];
|
|
119
120
|
//# sourceMappingURL=write-functions.js.map
|
package/util/mermaid/dfg.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type DataflowGraph } from '../../dataflow/graph/graph';
|
|
2
2
|
import { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
3
|
import { type IdentifierDefinition } from '../../dataflow/environments/identifier';
|
|
4
|
+
import { type DataflowGraphVertexInfo } from '../../dataflow/graph/vertex';
|
|
4
5
|
import { type MermaidMarkdownMark, type MermaidMarkStyle } from './info';
|
|
5
6
|
interface MermaidGraph {
|
|
6
7
|
nodeLines: string[];
|
|
@@ -15,6 +16,13 @@ interface MermaidGraph {
|
|
|
15
16
|
/** if given, the dataflow graph will only focus on the "important" parts */
|
|
16
17
|
simplified?: boolean;
|
|
17
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Translates a vertex tag to the corresponding mermaid node brackets.
|
|
21
|
+
*/
|
|
22
|
+
export declare function mermaidNodeBrackets(tag: DataflowGraphVertexInfo['tag']): {
|
|
23
|
+
open: string;
|
|
24
|
+
close: string;
|
|
25
|
+
};
|
|
18
26
|
/**
|
|
19
27
|
* Prints an identifier definition in a human-readable format.
|
|
20
28
|
*/
|
package/util/mermaid/dfg.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mermaidNodeBrackets = mermaidNodeBrackets;
|
|
3
4
|
exports.printIdentifier = printIdentifier;
|
|
4
5
|
exports.graphToMermaid = graphToMermaid;
|
|
5
6
|
exports.graphToMermaidUrl = graphToMermaidUrl;
|
|
@@ -89,6 +90,9 @@ function displayFunctionArgMapping(argMapping) {
|
|
|
89
90
|
function encodeEdge(from, to, types) {
|
|
90
91
|
return `${from}->${to}["${Array.from(types).join(':')}"]`;
|
|
91
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Translates a vertex tag to the corresponding mermaid node brackets.
|
|
95
|
+
*/
|
|
92
96
|
function mermaidNodeBrackets(tag) {
|
|
93
97
|
let open;
|
|
94
98
|
let close;
|
package/util/quads.js
CHANGED
|
@@ -130,16 +130,24 @@ function processLiteralEntry(value, key, obj, quads, config, index) {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
function processObjectEntry(key, value, obj, quads, config) {
|
|
133
|
-
if (config.ignore(key, value)) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
if (guardCycle(value)) {
|
|
133
|
+
if (config.ignore(key, value) || guardCycle(value)) {
|
|
137
134
|
return;
|
|
138
135
|
}
|
|
139
136
|
if ((0, objects_1.isObjectOrArray)(value)) {
|
|
140
137
|
if (Array.isArray(value)) {
|
|
141
138
|
processArrayEntries(key, value, obj, quads, config);
|
|
142
139
|
}
|
|
140
|
+
else if (value instanceof Map) {
|
|
141
|
+
for (const [mapKey, mapValue] of value.entries()) {
|
|
142
|
+
processObjectEntry('key-' + String(mapKey), mapValue, obj, quads, config);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (value instanceof Set) {
|
|
146
|
+
let i = 0;
|
|
147
|
+
for (const setValue of value.values()) {
|
|
148
|
+
processObjectEntry('idx-' + String(i++), setValue, obj, quads, config);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
143
151
|
else {
|
|
144
152
|
processObjectEntries(key, value, obj, quads, config);
|
|
145
153
|
}
|
|
@@ -152,10 +160,10 @@ let store = new Set();
|
|
|
152
160
|
function guardCycle(obj) {
|
|
153
161
|
// @ts-expect-error we do not care about the type here
|
|
154
162
|
if ((0, objects_1.isObjectOrArray)(obj) && 'id' in obj) {
|
|
155
|
-
if (store.has(obj
|
|
163
|
+
if (store.has(obj)) {
|
|
156
164
|
return true;
|
|
157
165
|
}
|
|
158
|
-
store.add(obj
|
|
166
|
+
store.add(obj);
|
|
159
167
|
}
|
|
160
168
|
return false;
|
|
161
169
|
}
|
package/util/range.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type SourcePosition = [
|
|
|
16
16
|
* Utility functions for {@link SourcePosition|source positions}.
|
|
17
17
|
*/
|
|
18
18
|
export declare const SourcePosition: {
|
|
19
|
+
readonly name: "SourcePosition";
|
|
19
20
|
/**
|
|
20
21
|
* Formats a {@link SourcePosition|source position} as a human-readable string.
|
|
21
22
|
*/
|
|
@@ -48,6 +49,7 @@ export type SourceRange = [
|
|
|
48
49
|
* Utility functions for {@link SourceRange|source ranges}.
|
|
49
50
|
*/
|
|
50
51
|
export declare const SourceRange: {
|
|
52
|
+
readonly name: "SourceRange";
|
|
51
53
|
/**
|
|
52
54
|
* Prints a {@link SourceRange|range} as a human-readable string.
|
|
53
55
|
*/
|
|
@@ -123,6 +125,7 @@ export type SourceLocation = [...r: SourceRange, f?: string];
|
|
|
123
125
|
* Utility functions for {@link SourceLocation|source locations}.
|
|
124
126
|
*/
|
|
125
127
|
export declare const SourceLocation: {
|
|
128
|
+
readonly name: "SourceLocation";
|
|
126
129
|
/**
|
|
127
130
|
* Formats a {@link SourceLocation|source location} as a human-readable string.
|
|
128
131
|
*/
|
package/util/range.js
CHANGED
|
@@ -6,6 +6,7 @@ const assert_1 = require("./assert");
|
|
|
6
6
|
* Utility functions for {@link SourcePosition|source positions}.
|
|
7
7
|
*/
|
|
8
8
|
exports.SourcePosition = {
|
|
9
|
+
name: 'SourcePosition',
|
|
9
10
|
/**
|
|
10
11
|
* Formats a {@link SourcePosition|source position} as a human-readable string.
|
|
11
12
|
*/
|
|
@@ -36,6 +37,7 @@ exports.SourcePosition = {
|
|
|
36
37
|
* Utility functions for {@link SourceRange|source ranges}.
|
|
37
38
|
*/
|
|
38
39
|
exports.SourceRange = {
|
|
40
|
+
name: 'SourceRange',
|
|
39
41
|
/**
|
|
40
42
|
* Prints a {@link SourceRange|range} as a human-readable string.
|
|
41
43
|
*/
|
|
@@ -157,6 +159,7 @@ exports.SourceRange = {
|
|
|
157
159
|
* Utility functions for {@link SourceLocation|source locations}.
|
|
158
160
|
*/
|
|
159
161
|
exports.SourceLocation = {
|
|
162
|
+
name: 'SourceLocation',
|
|
160
163
|
/**
|
|
161
164
|
* Formats a {@link SourceLocation|source location} as a human-readable string.
|
|
162
165
|
*/
|
package/util/version.js
CHANGED
|
@@ -6,7 +6,7 @@ exports.printVersionInformation = printVersionInformation;
|
|
|
6
6
|
const semver_1 = require("semver");
|
|
7
7
|
const assert_1 = require("./assert");
|
|
8
8
|
// this is automatically replaced with the current version by release-it
|
|
9
|
-
const version = '2.9.
|
|
9
|
+
const version = '2.9.12';
|
|
10
10
|
/**
|
|
11
11
|
* Retrieves the current flowR version as a new {@link SemVer} object.
|
|
12
12
|
*/
|